/*       */ package com.zimbra.cs.account.ldap;
/*       */ 
/*       */ import com.google.common.base.Strings;
/*       */ import com.google.common.collect.Lists;
/*       */ import com.google.common.collect.Maps;
/*       */ import com.google.common.collect.Sets;
/*       */ import com.zimbra.common.account.Key.AccountBy;
/*       */ import com.zimbra.common.account.Key.AlwaysOnClusterBy;
/*       */ import com.zimbra.common.account.Key.CacheEntryBy;
/*       */ import com.zimbra.common.account.Key.CalendarResourceBy;
/*       */ import com.zimbra.common.account.Key.CosBy;
/*       */ import com.zimbra.common.account.Key.DataSourceBy;
/*       */ import com.zimbra.common.account.Key.DistributionListBy;
/*       */ import com.zimbra.common.account.Key.DomainBy;
/*       */ import com.zimbra.common.account.Key.IdentityBy;
/*       */ import com.zimbra.common.account.Key.ServerBy;
/*       */ import com.zimbra.common.account.Key.ShareLocatorBy;
/*       */ import com.zimbra.common.account.Key.SignatureBy;
/*       */ import com.zimbra.common.account.Key.UCServiceBy;
/*       */ import com.zimbra.common.account.Key.XMPPComponentBy;
/*       */ import com.zimbra.common.account.Key.ZimletBy;
/*       */ import com.zimbra.common.account.ZAttrProvisioning.AccountCalendarUserType;
/*       */ import com.zimbra.common.account.ZAttrProvisioning.AutoProvAuthMech;
/*       */ import com.zimbra.common.account.ZAttrProvisioning.DomainType;
/*       */ import com.zimbra.common.localconfig.KnownKey;
/*       */ import com.zimbra.common.localconfig.LC;
/*       */ import com.zimbra.common.service.ServiceException;
/*       */ import com.zimbra.common.service.ServiceException.Argument;
/*       */ import com.zimbra.common.service.ServiceException.Argument.Type;
/*       */ import com.zimbra.common.soap.Element;
/*       */ import com.zimbra.common.util.DateUtil;
/*       */ import com.zimbra.common.util.EmailUtil;
/*       */ import com.zimbra.common.util.Log;
/*       */ import com.zimbra.common.util.SetUtil;
/*       */ import com.zimbra.common.util.StringUtil;
/*       */ import com.zimbra.common.util.ZimbraLog;
/*       */ import com.zimbra.cs.account.AccessManager.ViaGrant;
/*       */ import com.zimbra.cs.account.Account;
/*       */ import com.zimbra.cs.account.AccountServiceException;
/*       */ import com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException;
/*       */ import com.zimbra.cs.account.Alias;
/*       */ import com.zimbra.cs.account.AliasedEntry;
/*       */ import com.zimbra.cs.account.AlwaysOnCluster;
/*       */ import com.zimbra.cs.account.AttributeClass;
/*       */ import com.zimbra.cs.account.AttributeInfo;
/*       */ import com.zimbra.cs.account.AttributeManager;
/*       */ import com.zimbra.cs.account.CalendarResource;
/*       */ import com.zimbra.cs.account.Config;
/*       */ import com.zimbra.cs.account.Cos;
/*       */ import com.zimbra.cs.account.DataSource;
/*       */ import com.zimbra.cs.account.DistributionList;
/*       */ import com.zimbra.cs.account.Domain;
/*       */ import com.zimbra.cs.account.DynamicGroup;
/*       */ import com.zimbra.cs.account.Entry;
/*       */ import com.zimbra.cs.account.EntryCacheDataKey;
/*       */ import com.zimbra.cs.account.GalContact;
/*       */ import com.zimbra.cs.account.GalContact.Visitor;
/*       */ import com.zimbra.cs.account.GlobalGrant;
/*       */ import com.zimbra.cs.account.Group;
/*       */ import com.zimbra.cs.account.GroupedEntry;
/*       */ import com.zimbra.cs.account.GuestAccount;
/*       */ import com.zimbra.cs.account.IDNUtil;
/*       */ import com.zimbra.cs.account.Identity;
/*       */ import com.zimbra.cs.account.MailTarget;
/*       */ import com.zimbra.cs.account.NamedEntry;
/*       */ import com.zimbra.cs.account.NamedEntry.Visitor;
/*       */ import com.zimbra.cs.account.PreAuthKey;
/*       */ import com.zimbra.cs.account.Provisioning;
/*       */ import com.zimbra.cs.account.Provisioning.CacheEntry;
/*       */ import com.zimbra.cs.account.Provisioning.CacheMode;
/*       */ import com.zimbra.cs.account.Provisioning.CountAccountResult;
/*       */ import com.zimbra.cs.account.Provisioning.DirectoryEntryVisitor;
/*       */ import com.zimbra.cs.account.Provisioning.EagerAutoProvisionScheduler;
/*       */ import com.zimbra.cs.account.Provisioning.EntryType;
/*       */ import com.zimbra.cs.account.Provisioning.GalMode;
/*       */ import com.zimbra.cs.account.Provisioning.GroupMemberEmailAddrs;
/*       */ import com.zimbra.cs.account.Provisioning.GroupMembership;
/*       */ import com.zimbra.cs.account.Provisioning.MemberOf;
/*       */ import com.zimbra.cs.account.Provisioning.Result;
/*       */ import com.zimbra.cs.account.Provisioning.SearchGalResult;
/*       */ import com.zimbra.cs.account.Provisioning.SetPasswordResult;
/*       */ import com.zimbra.cs.account.ProvisioningExt.PostCreateAccountListener;
/*       */ import com.zimbra.cs.account.SearchAccountsOptions;
/*       */ import com.zimbra.cs.account.SearchAccountsOptions.IncludeType;
/*       */ import com.zimbra.cs.account.SearchDirectoryOptions;
/*       */ import com.zimbra.cs.account.SearchDirectoryOptions.MakeObjectOpt;
/*       */ import com.zimbra.cs.account.SearchDirectoryOptions.ObjectType;
/*       */ import com.zimbra.cs.account.SearchDirectoryOptions.SortOpt;
/*       */ import com.zimbra.cs.account.Server;
/*       */ import com.zimbra.cs.account.ShareLocator;
/*       */ import com.zimbra.cs.account.Signature;
/*       */ import com.zimbra.cs.account.UCService;
/*       */ import com.zimbra.cs.account.XMPPComponent;
/*       */ import com.zimbra.cs.account.Zimlet;
/*       */ import com.zimbra.cs.account.accesscontrol.GranteeType;
/*       */ import com.zimbra.cs.account.accesscontrol.PermissionCache;
/*       */ import com.zimbra.cs.account.accesscontrol.Right;
/*       */ import com.zimbra.cs.account.accesscontrol.RightCommand;
/*       */ import com.zimbra.cs.account.accesscontrol.RightCommand.EffectiveRights;
/*       */ import com.zimbra.cs.account.accesscontrol.RightModifier;
/*       */ import com.zimbra.cs.account.accesscontrol.TargetType;
/*       */ import com.zimbra.cs.account.auth.AuthContext.Protocol;
/*       */ import com.zimbra.cs.account.auth.AuthMechanism;
/*       */ import com.zimbra.cs.account.auth.AuthMechanism.AuthMech;
/*       */ import com.zimbra.cs.account.auth.PasswordUtil.SSHA;
/*       */ import com.zimbra.cs.account.auth.PasswordUtil.SSHA512;
/*       */ import com.zimbra.cs.account.cache.DomainCache.GetFromDomainCacheOption;
/*       */ import com.zimbra.cs.account.cache.DomainCache.NonExistingDomain;
/*       */ import com.zimbra.cs.account.cache.IAccountCache;
/*       */ import com.zimbra.cs.account.cache.IDomainCache;
/*       */ import com.zimbra.cs.account.cache.IMimeTypeCache;
/*       */ import com.zimbra.cs.account.cache.INamedEntryCache;
/*       */ import com.zimbra.cs.account.callback.CallbackContext;
/*       */ import com.zimbra.cs.account.callback.CallbackContext.DataKey;
/*       */ import com.zimbra.cs.account.callback.CallbackContext.Op;
/*       */ import com.zimbra.cs.account.gal.GalNamedFilter;
/*       */ import com.zimbra.cs.account.gal.GalOp;
/*       */ import com.zimbra.cs.account.gal.GalParams.ExternalGalParams;
/*       */ import com.zimbra.cs.account.gal.GalParams.ZimbraGalParams;
/*       */ import com.zimbra.cs.account.gal.GalUtil;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapAccount;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapAlwaysOnCluster;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapCalendarResource;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapConfig;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapCos;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapDataSource;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapDistributionList;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapDomain;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapDynamicGroup;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapDynamicGroup.DynamicUnit;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapDynamicGroup.StaticUnit;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapEntry;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapGlobalGrant;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapIdentity;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapMimeType;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapServer;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapShareLocator;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapSignature;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapUCService;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapXMPPComponent;
/*       */ import com.zimbra.cs.account.ldap.entry.LdapZimlet;
/*       */ import com.zimbra.cs.account.names.NameUtil;
/*       */ import com.zimbra.cs.account.names.NameUtil.EmailAddress;
/*       */ import com.zimbra.cs.gal.GalSearchControl;
/*       */ import com.zimbra.cs.gal.GalSearchParams;
/*       */ import com.zimbra.cs.gal.GalSearchResultCallback;
/*       */ import com.zimbra.cs.gal.GalSyncToken;
/*       */ import com.zimbra.cs.ldap.IAttributes;
/*       */ import com.zimbra.cs.ldap.IAttributes.CheckBinary;
/*       */ import com.zimbra.cs.ldap.ILdapContext;
/*       */ import com.zimbra.cs.ldap.LdapClient;
/*       */ import com.zimbra.cs.ldap.LdapException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapContextNotEmptyException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapEntryNotFoundException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapInvalidAttrNameException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapInvalidAttrValueException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapInvalidSearchFilterException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapMultipleEntriesMatchedException;
/*       */ import com.zimbra.cs.ldap.LdapException.LdapSizeLimitExceededException;
/*       */ import com.zimbra.cs.ldap.LdapServerConfig.ExternalLdapConfig;
/*       */ import com.zimbra.cs.ldap.LdapServerType;
/*       */ import com.zimbra.cs.ldap.LdapTODO.TODO;
/*       */ import com.zimbra.cs.ldap.LdapUsage;
/*       */ import com.zimbra.cs.ldap.LdapUtil;
/*       */ import com.zimbra.cs.ldap.SearchLdapOptions;
/*       */ import com.zimbra.cs.ldap.SearchLdapOptions.SearchLdapVisitor;
/*       */ import com.zimbra.cs.ldap.SearchLdapOptions.StopIteratingException;
/*       */ import com.zimbra.cs.ldap.ZAttributes;
/*       */ import com.zimbra.cs.ldap.ZLdapContext;
/*       */ import com.zimbra.cs.ldap.ZLdapFilter;
/*       */ import com.zimbra.cs.ldap.ZLdapFilterFactory;
/*       */ import com.zimbra.cs.ldap.ZLdapFilterFactory.FilterId;
/*       */ import com.zimbra.cs.ldap.ZLdapSchema;
/*       */ import com.zimbra.cs.ldap.ZLdapSchema.ZObjectClassDefinition;
/*       */ import com.zimbra.cs.ldap.ZMutableEntry;
/*       */ import com.zimbra.cs.ldap.ZSearchControls;
/*       */ import com.zimbra.cs.ldap.ZSearchResultEntry;
/*       */ import com.zimbra.cs.ldap.ZSearchResultEnumeration;
/*       */ import com.zimbra.cs.ldap.ZSearchScope;
/*       */ import com.zimbra.cs.ldap.unboundid.InMemoryLdapServer;
/*       */ import com.zimbra.cs.mime.MimeTypeInfo;
/*       */ import com.zimbra.cs.util.Zimbra;
/*       */ import com.zimbra.cs.zimlet.ZimletException;
/*       */ import com.zimbra.soap.admin.type.CacheEntryType;
/*       */ import com.zimbra.soap.admin.type.CountObjectsType;
/*       */ import com.zimbra.soap.admin.type.DataSourceType;
/*       */ import com.zimbra.soap.admin.type.GranteeSelector.GranteeBy;
/*       */ import com.zimbra.soap.type.AutoProvPrincipalBy;
/*       */ import com.zimbra.soap.type.GalSearchType;
/*       */ import com.zimbra.soap.type.TargetBy;
/*       */ import java.io.IOException;
/*       */ import java.io.PrintWriter;
/*       */ import java.util.ArrayList;
/*       */ import java.util.Arrays;
/*       */ import java.util.Collection;
/*       */ import java.util.Collections;
/*       */ import java.util.Comparator;
/*       */ import java.util.Date;
/*       */ import java.util.HashMap;
/*       */ import java.util.HashSet;
/*       */ import java.util.Iterator;
/*       */ import java.util.List;
/*       */ import java.util.Map;
/*       */ import java.util.Map.Entry;
/*       */ import java.util.Random;
/*       */ import java.util.Set;
/*       */ import java.util.Stack;
/*       */ import java.util.TreeSet;
/*       */ import java.util.regex.Matcher;
/*       */ import java.util.regex.Pattern;
/*       */ import java.util.regex.PatternSyntaxException;
/*       */ 
/*       */ public class LdapProvisioning extends LdapProv implements com.zimbra.cs.account.CacheAwareProvisioning
/*       */ {
/*   216 */   private static final Log mLog = com.zimbra.common.util.LogFactory.getLog(LdapProvisioning.class);
/*       */   
/*   218 */   private static final String[] sInvalidAccountCreateModifyAttrs = { "uid", "zimbraMailAlias", "zimbraMailDeliveryAddress" };
/*       */   
/*       */   private boolean useCache;
/*       */   
/*       */   private LdapCache cache;
/*       */   
/*       */   private final IAccountCache accountCache;
/*       */   
/*       */   private final INamedEntryCache<LdapCos> cosCache;
/*       */   
/*       */   private final IDomainCache domainCache;
/*       */   
/*       */   private final INamedEntryCache<Group> groupCache;
/*       */   
/*       */   private final IMimeTypeCache mimeTypeCache;
/*       */   
/*       */   private final INamedEntryCache<Server> serverCache;
/*       */   private final INamedEntryCache<AlwaysOnCluster> alwaysOnClusterCache;
/*       */   private final INamedEntryCache<UCService> ucServiceCache;
/*       */   private final INamedEntryCache<ShareLocator> shareLocatorCache;
/*       */   private final INamedEntryCache<XMPPComponent> xmppComponentCache;
/*       */   private final INamedEntryCache<LdapZimlet> zimletCache;
/*   240 */   private LdapConfig cachedGlobalConfig = null;
/*   241 */   private GlobalGrant cachedGlobalGrant = null;
/*   242 */   private static final Random sPoolRandom = new Random();
/*       */   
/*       */   private final Groups allDLs;
/*       */   
/*       */   private final ZLdapFilterFactory filterFactory;
/*       */   private String[] BASIC_DL_ATTRS;
/*       */   private String[] BASIC_DYNAMIC_GROUP_ATTRS;
/*       */   private String[] BASIC_GROUP_ATTRS;
/*   250 */   private static LdapProvisioning singleton = null;
/*       */   
/*       */   private static synchronized void ensureSingleton(LdapProvisioning prov) {
/*   253 */     if (singleton != null)
/*       */     {
/*   255 */       Zimbra.halt("Only one instance of LdapProvisioning can be created", ServiceException.FAILURE("failed to instantiate LdapProvisioning", null));
/*       */     }
/*       */     
/*   258 */     singleton = prov;
/*       */   }
/*       */   
/*       */   public LdapProvisioning() {
/*   262 */     this(Provisioning.CacheMode.DEFAULT);
/*       */   }
/*       */   
/*       */   public LdapProvisioning(Provisioning.CacheMode cacheMode) {
/*   266 */     ensureSingleton(this);
/*       */     
/*   268 */     this.useCache = true;
/*   269 */     if (cacheMode == Provisioning.CacheMode.OFF) {
/*   270 */       this.useCache = false;
/*       */     }
/*       */     
/*   273 */     if (this.useCache) {
/*   274 */       this.cache = new LdapCache.LRUMapCache();
/*       */     } else {
/*   276 */       this.cache = new LdapCache.NoopCache();
/*       */     }
/*       */     
/*   279 */     this.accountCache = this.cache.accountCache();
/*   280 */     this.cosCache = this.cache.cosCache();
/*   281 */     this.domainCache = this.cache.domainCache();
/*   282 */     this.groupCache = this.cache.groupCache();
/*   283 */     this.mimeTypeCache = this.cache.mimeTypeCache();
/*   284 */     this.serverCache = this.cache.serverCache();
/*   285 */     this.ucServiceCache = this.cache.ucServiceCache();
/*   286 */     this.shareLocatorCache = this.cache.shareLocatorCache();
/*   287 */     this.xmppComponentCache = this.cache.xmppComponentCache();
/*   288 */     this.zimletCache = this.cache.zimletCache();
/*   289 */     this.alwaysOnClusterCache = this.cache.alwaysOnClusterCache();
/*       */     
/*   291 */     setDIT();
/*   292 */     setHelper(new ZLdapHelper(this));
/*   293 */     this.allDLs = new Groups(this);
/*       */     
/*   295 */     this.filterFactory = ZLdapFilterFactory.getInstance();
/*       */     try
/*       */     {
/*   298 */       this.BASIC_DL_ATTRS = getBasicDLAttrs();
/*   299 */       this.BASIC_DYNAMIC_GROUP_ATTRS = getBasicDynamicGroupAttrs();
/*   300 */       this.BASIC_GROUP_ATTRS = getBasicGroupAttrs();
/*       */     } catch (ServiceException e) {
/*   302 */       Zimbra.halt("failed to initialize LdapProvisioning", e);
/*       */     }
/*       */     
/*   305 */     register(new Validators.DomainAccountValidator());
/*   306 */     register(new Validators.DomainMaxAccountsValidator());
/*       */   }
/*       */   
/*       */   public int getAccountCacheSize()
/*       */   {
/*   311 */     return this.accountCache.getSize();
/*       */   }
/*       */   
/*   314 */   public double getAccountCacheHitRate() { return this.accountCache.getHitRate(); }
/*       */   
/*       */   public int getCosCacheSize() {
/*   317 */     return this.cosCache.getSize();
/*       */   }
/*       */   
/*   320 */   public double getCosCacheHitRate() { return this.cosCache.getHitRate(); }
/*       */   
/*       */   public int getDomainCacheSize() {
/*   323 */     return this.domainCache.getSize();
/*       */   }
/*       */   
/*   326 */   public double getDomainCacheHitRate() { return this.domainCache.getHitRate(); }
/*       */   
/*       */   public int getServerCacheSize() {
/*   329 */     return this.serverCache.getSize();
/*       */   }
/*       */   
/*   332 */   public double getServerCacheHitRate() { return this.serverCache.getHitRate(); }
/*       */   
/*       */   public int getUCServiceCacheSize() {
/*   335 */     return this.ucServiceCache.getSize();
/*       */   }
/*       */   
/*   338 */   public double getUCServiceCacheHitRate() { return this.ucServiceCache.getHitRate(); }
/*       */   
/*       */   public int getZimletCacheSize() {
/*   341 */     return this.zimletCache.getSize();
/*       */   }
/*       */   
/*   344 */   public double getZimletCacheHitRate() { return this.zimletCache.getHitRate(); }
/*       */   
/*       */   public int getGroupCacheSize() {
/*   347 */     return this.groupCache.getSize();
/*       */   }
/*       */   
/*   350 */   public double getGroupCacheHitRate() { return this.groupCache.getHitRate(); }
/*       */   
/*       */   public int getXMPPCacheSize() {
/*   353 */     return this.xmppComponentCache.getSize();
/*       */   }
/*       */   
/*   356 */   public double getXMPPCacheHitRate() { return this.xmppComponentCache.getHitRate(); }
/*       */   
/*       */   private String[] getBasicDLAttrs() throws ServiceException {
/*   359 */     AttributeManager attrMgr = AttributeManager.getInstance();
/*   360 */     Set<String> dlAttrs = attrMgr.getAllAttrsInClass(AttributeClass.distributionList);
/*       */     
/*   362 */     Set<String> attrs = Sets.newHashSet(dlAttrs);
/*   363 */     attrs.add("objectClass");
/*   364 */     attrs.remove("zimbraMailForwardingAddress");
/*   365 */     attrs.remove("zimbraMailTransport");
/*       */     
/*       */ 
/*   368 */     for (Iterator<String> iter = attrs.iterator(); iter.hasNext();) {
/*   369 */       String attr = (String)iter.next();
/*   370 */       AttributeInfo ai = attrMgr.getAttributeInfo(attr);
/*   371 */       if ((ai != null) && (ai.isDeprecated())) {
/*   372 */         iter.remove();
/*       */       }
/*       */     }
/*       */     
/*   376 */     return (String[])Lists.newArrayList(attrs).toArray(new String[attrs.size()]);
/*       */   }
/*       */   
/*       */   private String[] getBasicDynamicGroupAttrs() throws ServiceException {
/*   380 */     AttributeManager attrMgr = AttributeManager.getInstance();
/*   381 */     Set<String> dynGroupAttrs = attrMgr.getAllAttrsInClass(AttributeClass.group);
/*       */     
/*   383 */     Set<String> attrs = Sets.newHashSet(dynGroupAttrs);
/*   384 */     attrs.add("objectClass");
/*       */     
/*       */ 
/*   387 */     for (Iterator<String> iter = attrs.iterator(); iter.hasNext();) {
/*   388 */       String attr = (String)iter.next();
/*   389 */       AttributeInfo ai = attrMgr.getAttributeInfo(attr);
/*   390 */       if ((ai != null) && (ai.isDeprecated())) {
/*   391 */         iter.remove();
/*       */       }
/*       */     }
/*       */     
/*   395 */     return (String[])Lists.newArrayList(attrs).toArray(new String[attrs.size()]);
/*       */   }
/*       */   
/*       */   private String[] getBasicGroupAttrs() throws ServiceException {
/*   399 */     Set<String> attrs = Sets.newHashSet();
/*       */     
/*   401 */     Set<String> dlAttrs = Sets.newHashSet(getBasicDLAttrs());
/*   402 */     Set<String> dynGroupAttrs = Sets.newHashSet(getBasicDynamicGroupAttrs());
/*   403 */     SetUtil.union(attrs, dlAttrs, dynGroupAttrs);
/*   404 */     return (String[])Lists.newArrayList(attrs).toArray(new String[attrs.size()]);
/*       */   }
/*       */   
/*       */   protected static class ReplaceAddressResult
/*       */   {
/*       */     private final String[] mOldAddrs;
/*       */     private final String[] mNewAddrs;
/*       */     
/*       */     ReplaceAddressResult(String[] oldAddrs, String[] newAddrs) {
/*   413 */       this.mOldAddrs = oldAddrs;
/*   414 */       this.mNewAddrs = newAddrs;
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*   419 */     public String[] oldAddrs() { return this.mOldAddrs; }
/*   420 */     public String[] newAddrs() { return this.mNewAddrs; }
/*       */   }
/*       */   
/*       */   public void modifyAttrs(Entry e, Map<String, ? extends Object> attrs, boolean checkImmutable)
/*       */     throws ServiceException
/*       */   {
/*   426 */     modifyAttrs(e, attrs, checkImmutable, true);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public void modifyAttrs(Entry e, Map<String, ? extends Object> attrs, boolean checkImmutable, boolean allowCallback)
/*       */     throws ServiceException
/*       */   {
/*   445 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.MODIFY);
/*   446 */     AttributeManager.getInstance().preModify(attrs, e, callbackContext, checkImmutable, allowCallback);
/*   447 */     modifyAttrsInternal(e, null, attrs);
/*   448 */     AttributeManager.getInstance().postModify(attrs, e, callbackContext, allowCallback);
/*       */   }
/*       */   
/*       */   public void restoreAccountAttrs(Account acct, Map<String, ? extends Object> backupAttrs)
/*       */     throws ServiceException
/*       */   {
/*   454 */     Map<String, Object> attrs = Maps.newHashMap(backupAttrs);
/*       */     
/*   456 */     Object ocsInBackupObj = backupAttrs.get("objectClass");
/*   457 */     String[] ocsInBackup = StringUtil.toStringArray(ocsInBackupObj);
/*       */     
/*   459 */     String[] ocsOnAcct = acct.getMultiAttr("objectClass");
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*   464 */     List<String> needOCs = Lists.newArrayList(ocsOnAcct);
/*   465 */     for (String oc : ocsInBackup) {
/*   466 */       if ((!LdapObjectClassHierarchy.isSuperiorOC(this, LdapObjectClass.ZIMBRA_DEFAULT_PERSON_OC, oc)) && 
/*   467 */         (!needOCs.contains(oc))) {
/*   468 */         needOCs.add(oc);
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*   473 */     attrs.put("objectClass", needOCs.toArray(new String[needOCs.size()]));
/*       */     
/*   475 */     modifyAttrs(acct, attrs, false, false);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   protected void modifyAttrsInternal(Entry entry, ZLdapContext initZlc, Map<String, ? extends Object> attrs)
/*       */     throws ServiceException
/*       */   {
/*   488 */     if (((entry instanceof Account)) && (!(entry instanceof CalendarResource))) {
/*   489 */       Account acct = (Account)entry;
/*   490 */       validate("modifyAccountCheckDomainCosAndFeature", new Object[] { acct.getAttr("zimbraMailDeliveryAddress"), attrs, acct });
/*       */     }
/*       */     
/*       */ 
/*   494 */     modifyLdapAttrs(entry, initZlc, attrs);
/*       */   }
/*       */   
/*       */   private void modifyLdapAttrs(Entry entry, ZLdapContext initZlc, Map<String, ? extends Object> attrs)
/*       */     throws ServiceException
/*       */   {
/*   500 */     ZLdapContext zlc = initZlc;
/*       */     try {
/*   502 */       if (zlc == null) {
/*   503 */         zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.modifyEntryfromEntryType(entry.getEntryType()));
/*       */       }
/*       */       
/*   506 */       this.helper.modifyAttrs(zlc, ((LdapEntry)entry).getDN(), attrs, entry);
/*       */     } catch (LdapException.LdapInvalidAttrNameException e) {
/*   508 */       throw AccountServiceException.INVALID_ATTR_NAME("invalid attr name: " + e.getMessage(), e);
/*       */     }
/*       */     catch (LdapException.LdapInvalidAttrValueException e) {
/*   511 */       throw AccountServiceException.INVALID_ATTR_VALUE("invalid attr value: " + e.getMessage(), e);
/*       */     }
/*       */     catch (ServiceException e) {
/*   514 */       throw ServiceException.FAILURE("unable to modify attrs: " + e.getMessage(), e);
/*       */     }
/*       */     finally {
/*   517 */       refreshEntry(entry, zlc);
/*   518 */       if (initZlc == null) {
/*   519 */         LdapClient.closeContext(zlc);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   private void setLdapPassword(Entry entry, ZLdapContext initZlc, String newPassword) throws ServiceException
/*       */   {
/*   526 */     ZLdapContext zlc = initZlc;
/*       */     try {
/*   528 */       if (zlc == null) {
/*   529 */         zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.SET_PASSWORD);
/*       */       }
/*       */       
/*   532 */       zlc.setPassword(((LdapEntry)entry).getDN(), newPassword);
/*       */     } catch (ServiceException e) {
/*   534 */       throw ServiceException.FAILURE("unable to set password: " + e.getMessage(), e);
/*       */     }
/*       */     finally {
/*   537 */       refreshEntry(entry, zlc);
/*   538 */       if (initZlc == null) {
/*   539 */         LdapClient.closeContext(zlc);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public void reload(Entry e)
/*       */     throws ServiceException
/*       */   {
/*   549 */     reload(e, true);
/*       */   }
/*       */   
/*       */   public void reload(Entry e, boolean master)
/*       */     throws ServiceException
/*       */   {
/*   555 */     ZLdapContext zlc = null;
/*       */     try {
/*   557 */       zlc = LdapClient.getContext(LdapServerType.get(master), LdapUsage.GET_ENTRY);
/*   558 */       refreshEntry(e, zlc);
/*       */     } finally {
/*   560 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   void refreshEntry(Entry entry, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*       */     try {
/*   567 */       String dn = ((LdapEntry)entry).getDN();
/*   568 */       ZAttributes attributes = this.helper.getAttributes(initZlc, dn);
/*       */       
/*   570 */       Map<String, Object> attrs = attributes.getAttrs();
/*       */       
/*   572 */       Map<String, Object> defaults = null;
/*   573 */       Map<String, Object> secondaryDefaults = null;
/*   574 */       Map<String, Object> overrideDefaults = null;
/*       */       
/*   576 */       if ((entry instanceof Account))
/*       */       {
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*   599 */         Account temp = makeAccountNoDefaults(dn, attributes);
/*   600 */         Cos cos = getCOS(temp);
/*   601 */         if (cos != null)
/*   602 */           defaults = cos.getAccountDefaults();
/*   603 */         Domain domain = getDomain((Account)entry);
/*   604 */         if (domain != null)
/*   605 */           secondaryDefaults = domain.getAccountDefaults();
/*   606 */       } else if ((entry instanceof Domain)) {
/*   607 */         defaults = getConfig().getDomainDefaults();
/*   608 */       } else if ((entry instanceof Server)) {
/*   609 */         defaults = getConfig().getServerDefaults();
/*   610 */         AlwaysOnCluster aoc = getAlwaysOnCluster((Server)entry);
/*   611 */         if (aoc != null) {
/*   612 */           overrideDefaults = aoc.getServerOverrides();
/*       */         }
/*       */       }
/*       */       
/*   616 */       if ((defaults == null) && (secondaryDefaults == null)) {
/*   617 */         entry.setAttrs(attrs);
/*       */       } else {
/*   619 */         entry.setAttrs(attrs, defaults, secondaryDefaults, overrideDefaults);
/*       */       }
/*   621 */       extendLifeInCacheOrFlush(entry);
/*       */     }
/*       */     catch (ServiceException e) {
/*   624 */       throw ServiceException.FAILURE("unable to refresh entry", e);
/*       */     }
/*       */   }
/*       */   
/*       */   public void extendLifeInCacheOrFlush(Entry entry) {
/*   629 */     if ((entry instanceof Account)) {
/*   630 */       this.accountCache.replace((Account)entry);
/*   631 */     } else if ((entry instanceof LdapCos)) {
/*   632 */       this.cosCache.replace((LdapCos)entry);
/*   633 */     } else if ((entry instanceof Domain)) {
/*   634 */       this.domainCache.replace((Domain)entry);
/*   635 */     } else if ((entry instanceof Server)) {
/*   636 */       this.serverCache.replace((Server)entry);
/*   637 */     } else if ((entry instanceof UCService)) {
/*   638 */       this.ucServiceCache.replace((UCService)entry);
/*   639 */     } else if ((entry instanceof XMPPComponent)) {
/*   640 */       this.xmppComponentCache.replace((XMPPComponent)entry);
/*   641 */     } else if ((entry instanceof LdapZimlet)) {
/*   642 */       this.zimletCache.replace((LdapZimlet)entry);
/*   643 */     } else if ((entry instanceof LdapAlwaysOnCluster)) {
/*   644 */       this.alwaysOnClusterCache.replace((AlwaysOnCluster)entry);
/*   645 */     } else if ((entry instanceof Group))
/*       */     {
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*   658 */       Group modifiedInstance = (Group)entry;
/*   659 */       Group cachedInstance = getGroupFromCache(Key.DistributionListBy.id, modifiedInstance.getId());
/*   660 */       if ((cachedInstance != null) && (modifiedInstance != cachedInstance)) {
/*   661 */         this.groupCache.remove(cachedInstance);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public boolean healthCheck()
/*       */     throws ServiceException
/*       */   {
/*   671 */     boolean result = false;
/*       */     try
/*       */     {
/*   674 */       ZAttributes attrs = this.helper.getAttributes(LdapUsage.HEALTH_CHECK, this.mDIT.configDN());
/*   675 */       result = attrs != null;
/*       */     } catch (ServiceException e) {
/*   677 */       mLog.warn("LDAP health check error", e);
/*       */     }
/*   679 */     return result;
/*       */   }
/*       */   
/*       */   public synchronized Config getConfig()
/*       */     throws ServiceException
/*       */   {
/*   685 */     if (this.cachedGlobalConfig == null) {
/*   686 */       String configDn = this.mDIT.configDN();
/*       */       try {
/*   688 */         ZAttributes attrs = this.helper.getAttributes(LdapUsage.GET_GLOBALCONFIG, configDn);
/*   689 */         LdapConfig config = new LdapConfig(configDn, attrs, this);
/*       */         
/*   691 */         if (this.useCache) {
/*   692 */           this.cachedGlobalConfig = config;
/*       */         } else {
/*   694 */           return config;
/*       */         }
/*       */       } catch (ServiceException e) {
/*   697 */         throw ServiceException.FAILURE("unable to get config", e);
/*       */       }
/*       */     }
/*   700 */     return this.cachedGlobalConfig;
/*       */   }
/*       */   
/*       */   public synchronized GlobalGrant getGlobalGrant()
/*       */     throws ServiceException
/*       */   {
/*   706 */     if (this.cachedGlobalGrant == null) {
/*   707 */       String globalGrantDn = this.mDIT.globalGrantDN();
/*       */       try {
/*   709 */         ZAttributes attrs = this.helper.getAttributes(LdapUsage.GET_GLOBALGRANT, globalGrantDn);
/*   710 */         LdapGlobalGrant globalGrant = new LdapGlobalGrant(globalGrantDn, attrs, this);
/*       */         
/*   712 */         if (this.useCache) {
/*   713 */           this.cachedGlobalGrant = globalGrant;
/*       */         } else {
/*   715 */           return globalGrant;
/*       */         }
/*       */       } catch (ServiceException e) {
/*   718 */         throw ServiceException.FAILURE("unable to get globalgrant", e);
/*       */       }
/*       */     }
/*   721 */     return this.cachedGlobalGrant;
/*       */   }
/*       */   
/*       */   public List<MimeTypeInfo> getMimeTypes(String mimeType) throws ServiceException
/*       */   {
/*   726 */     return this.mimeTypeCache.getMimeTypes(this, mimeType);
/*       */   }
/*       */   
/*       */   public List<MimeTypeInfo> getMimeTypesByQuery(String mimeType) throws ServiceException
/*       */   {
/*   731 */     List<MimeTypeInfo> mimeTypes = new ArrayList();
/*       */     try
/*       */     {
/*   734 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.mimeBaseDN(), this.filterFactory.mimeEntryByMimeType(mimeType), ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*   736 */       while (ne.hasMore()) {
/*   737 */         ZSearchResultEntry sr = ne.next();
/*   738 */         mimeTypes.add(new LdapMimeType(sr, this));
/*       */       }
/*   740 */       ne.close();
/*       */     } catch (ServiceException e) {
/*   742 */       throw ServiceException.FAILURE("unable to get mime types for " + mimeType, e);
/*       */     }
/*   744 */     return mimeTypes;
/*       */   }
/*       */   
/*       */   public List<MimeTypeInfo> getAllMimeTypes() throws ServiceException
/*       */   {
/*   749 */     return this.mimeTypeCache.getAllMimeTypes(this);
/*       */   }
/*       */   
/*       */   public List<MimeTypeInfo> getAllMimeTypesByQuery() throws ServiceException
/*       */   {
/*   754 */     List<MimeTypeInfo> mimeTypes = new ArrayList();
/*       */     try
/*       */     {
/*   757 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.mimeBaseDN(), this.filterFactory.allMimeEntries(), ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*       */ 
/*   760 */       while (ne.hasMore()) {
/*   761 */         ZSearchResultEntry sr = ne.next();
/*   762 */         mimeTypes.add(new LdapMimeType(sr, this));
/*       */       }
/*   764 */       ne.close();
/*       */     } catch (ServiceException e) {
/*   766 */       throw ServiceException.FAILURE("unable to get mime types", e);
/*       */     }
/*   768 */     return mimeTypes;
/*       */   }
/*       */   
/*       */   private ZSearchResultEntry getSearchResultForAccountByQuery(String base, ZLdapFilter filter, ZLdapContext initZlc, boolean loadFromMaster, String[] returnAttrs) throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*   775 */       return this.helper.searchForEntry(base, filter, initZlc, loadFromMaster, returnAttrs);
/*       */     }
/*       */     catch (LdapException.LdapMultipleEntriesMatchedException e)
/*       */     {
/*   779 */       ZimbraLog.account.debug(e.getMessage());
/*   780 */       throw AccountServiceException.MULTIPLE_ACCOUNTS_MATCHED(String.format("multiple entries are returned by query: base=%s, query=%s", new Object[] { e.getQueryBase(), e.getQuery() }));
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   private Account getAccountByQuery(String base, ZLdapFilter filter, ZLdapContext initZlc, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*   790 */       ZSearchResultEntry sr = getSearchResultForAccountByQuery(base, filter, initZlc, loadFromMaster, null);
/*   791 */       if (sr != null) {
/*   792 */         return makeAccount(sr.getDN(), sr.getAttributes());
/*       */       }
/*       */     } catch (ServiceException e) {
/*   795 */       throw ServiceException.FAILURE("unable to lookup account via query: " + filter.toFilterString() + " message: " + e.getMessage(), e);
/*       */     }
/*       */     
/*   798 */     return null;
/*       */   }
/*       */   
/*       */   private Account getAccountById(String zimbraId, ZLdapContext zlc, boolean loadFromMaster) throws ServiceException
/*       */   {
/*   803 */     if (zimbraId == null)
/*   804 */       return null;
/*   805 */     Account a = this.accountCache.getById(zimbraId);
/*   806 */     if (a == null) {
/*   807 */       ZLdapFilter filter = this.filterFactory.accountById(zimbraId);
/*       */       
/*   809 */       a = getAccountByQuery(this.mDIT.mailBranchBaseDN(), filter, zlc, loadFromMaster);
/*       */       
/*       */ 
/*   812 */       if ((a == null) && (!this.mDIT.isUnder(this.mDIT.mailBranchBaseDN(), this.mDIT.adminBaseDN()))) {
/*   813 */         a = getAccountByQuery(this.mDIT.adminBaseDN(), filter, zlc, loadFromMaster);
/*       */       }
/*   815 */       this.accountCache.put(a);
/*       */     }
/*   817 */     return a;
/*       */   }
/*       */   
/*       */   public String getDNforAccount(Account acct, ZLdapContext zlc, boolean loadFromMaster) {
/*   821 */     if (acct == null) {
/*   822 */       return null;
/*       */     }
/*   824 */     if ((acct instanceof LdapAccount)) {
/*   825 */       return ((LdapAccount)acct).getDN();
/*       */     }
/*   827 */     return getDNforAccountById(acct.getId(), zlc, loadFromMaster);
/*       */   }
/*       */   
/*       */   public String getDNforAccountById(String zimbraId, ZLdapContext zlc, boolean loadFromMaster) {
/*   831 */     if (zimbraId == null) {
/*   832 */       return null;
/*       */     }
/*   834 */     ZLdapFilter filter = this.filterFactory.accountById(zimbraId);
/*       */     try {
/*   836 */       String[] retAttrs = { "zimbraId" };
/*       */       
/*   838 */       ZSearchResultEntry sr = getSearchResultForAccountByQuery(this.mDIT.mailBranchBaseDN(), filter, zlc, loadFromMaster, retAttrs);
/*       */       
/*   840 */       if ((sr == null) && (!this.mDIT.isUnder(this.mDIT.mailBranchBaseDN(), this.mDIT.adminBaseDN()))) {
/*   841 */         sr = getSearchResultForAccountByQuery(this.mDIT.adminBaseDN(), filter, zlc, loadFromMaster, retAttrs);
/*       */       }
/*   843 */       if (sr != null) {
/*   844 */         return sr.getDN();
/*       */       }
/*       */     } catch (ServiceException e) {
/*   847 */       ZimbraLog.search.debug("unable to lookup DN for account via query: %s", filter.toFilterString(), e);
/*       */     }
/*   849 */     return null;
/*       */   }
/*       */   
/*       */   public Account get(Key.AccountBy keyType, String key) throws ServiceException
/*       */   {
/*   854 */     return get(keyType, key, false);
/*       */   }
/*       */   
/*       */   public Account get(Key.AccountBy keyType, String key, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*   860 */     switch (keyType) {
/*       */     case adminName: 
/*   862 */       return getAdminAccountByName(key, loadFromMaster);
/*       */     case appAdminName: 
/*   864 */       return getAppAdminAccountByName(key, loadFromMaster);
/*       */     case id: 
/*   866 */       return getAccountById(key, null, loadFromMaster);
/*       */     case foreignPrincipal: 
/*   868 */       return getAccountByForeignPrincipal(key, loadFromMaster);
/*       */     case name: 
/*   870 */       return getAccountByName(key, loadFromMaster);
/*       */     case krb5Principal: 
/*   872 */       return com.zimbra.cs.account.krb5.Krb5Principal.getAccountFromKrb5Principal(key, loadFromMaster);
/*       */     }
/*   874 */     return null;
/*       */   }
/*       */   
/*       */   public Account getFromCache(Key.AccountBy keyType, String key) throws ServiceException
/*       */   {
/*   879 */     switch (keyType) {
/*       */     case adminName: 
/*   881 */       return this.accountCache.getByName(key);
/*       */     case id: 
/*   883 */       return this.accountCache.getById(key);
/*       */     case foreignPrincipal: 
/*   885 */       return this.accountCache.getByForeignPrincipal(key);
/*       */     case name: 
/*   887 */       return this.accountCache.getByName(key);
/*       */     case krb5Principal: 
/*   889 */       throw ServiceException.FAILURE("key type krb5Principal is not supported by getFromCache", null);
/*       */     }
/*   891 */     return null;
/*       */   }
/*       */   
/*       */   private Account getAccountByForeignPrincipal(String foreignPrincipal, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*   897 */     Account a = this.accountCache.getByForeignPrincipal(foreignPrincipal);
/*       */     
/*       */ 
/*   900 */     Account acct = getAccountByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.accountByForeignPrincipal(foreignPrincipal), null, loadFromMaster);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*   908 */     if (a == null) {
/*   909 */       a = acct;
/*   910 */       this.accountCache.put(a);
/*       */     }
/*   912 */     return a;
/*       */   }
/*       */   
/*       */   private Account getAdminAccountByName(String name, boolean loadFromMaster) throws ServiceException
/*       */   {
/*   917 */     Account a = this.accountCache.getByName(name);
/*   918 */     if (a == null) {
/*   919 */       a = getAccountByQuery(this.mDIT.adminBaseDN(), this.filterFactory.adminAccountByRDN(this.mDIT.accountNamingRdnAttr(), name), null, loadFromMaster);
/*       */       
/*       */ 
/*       */ 
/*   923 */       this.accountCache.put(a);
/*       */     }
/*   925 */     return a;
/*       */   }
/*       */   
/*       */   private Account getAppAdminAccountByName(String name, boolean loadFromMaster) throws ServiceException
/*       */   {
/*   930 */     Account a = this.accountCache.getByName(name);
/*   931 */     if (a == null) {
/*   932 */       a = getAccountByQuery(this.mDIT.appAdminBaseDN(), this.filterFactory.adminAccountByRDN(this.mDIT.accountNamingRdnAttr(), name), null, loadFromMaster);
/*       */       
/*       */ 
/*       */ 
/*   936 */       this.accountCache.put(a);
/*       */     }
/*   938 */     return a;
/*       */   }
/*       */   
/*       */   private String fixupAccountName(String emailAddress) throws ServiceException {
/*   942 */     int index = emailAddress.indexOf('@');
/*   943 */     String domain = null;
/*   944 */     if (index == -1)
/*       */     {
/*   946 */       domain = getConfig().getAttr("zimbraDefaultDomainName", null);
/*   947 */       if (domain == null) {
/*   948 */         throw ServiceException.INVALID_REQUEST("must be valid email address: " + emailAddress, null);
/*       */       }
/*   950 */       emailAddress = emailAddress + "@" + domain;
/*       */     } else {
/*   952 */       emailAddress = IDNUtil.toAsciiEmail(emailAddress);
/*       */     }
/*   954 */     return emailAddress;
/*       */   }
/*       */   
/*       */   Account getAccountByName(String emailAddress, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*   960 */     return getAccountByName(emailAddress, loadFromMaster, true);
/*       */   }
/*       */   
/*       */   Account getAccountByName(String emailAddress, boolean loadFromMaster, boolean checkAliasDomain)
/*       */     throws ServiceException
/*       */   {
/*   966 */     Account account = getAccountByNameInternal(emailAddress, loadFromMaster);
/*       */     
/*       */ 
/*       */ 
/*   970 */     if ((account == null) && 
/*   971 */       (checkAliasDomain)) {
/*   972 */       String addrByDomainAlias = getEmailAddrByDomainAlias(emailAddress);
/*   973 */       if (addrByDomainAlias != null) {
/*   974 */         account = getAccountByNameInternal(addrByDomainAlias, loadFromMaster);
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*   979 */     return account;
/*       */   }
/*       */   
/*       */   private Account getAccountByNameInternal(String emailAddress, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*   985 */     emailAddress = fixupAccountName(emailAddress);
/*       */     
/*   987 */     Account account = this.accountCache.getByName(emailAddress);
/*   988 */     if (account == null) {
/*   989 */       account = getAccountByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.accountByName(emailAddress), null, loadFromMaster);
/*       */       
/*       */ 
/*       */ 
/*   993 */       this.accountCache.put(account);
/*       */     }
/*   995 */     return account;
/*       */   }
/*       */   
/*       */ 
/*       */   public Account getAccountByForeignName(String foreignName, String application, Domain domain)
/*       */     throws ServiceException
/*       */   {
/*  1002 */     Account acct = getAccountByForeignPrincipal(application + ":" + foreignName);
/*       */     
/*  1004 */     if (acct != null) {
/*  1005 */       return acct;
/*       */     }
/*  1007 */     if (domain == null) {
/*  1008 */       String[] parts = foreignName.split("@");
/*  1009 */       if (parts.length != 2) {
/*  1010 */         return null;
/*       */       }
/*  1012 */       String domainName = parts[1];
/*  1013 */       domain = getDomain(Key.DomainBy.foreignName, application + ":" + domainName, true);
/*       */     }
/*       */     
/*  1016 */     if (domain == null) {
/*  1017 */       return null;
/*       */     }
/*       */     
/*  1020 */     DomainNameMappingHandler.HandlerConfig handlerConfig = DomainNameMappingHandler.getHandlerConfig(domain, application);
/*       */     
/*       */     String acctName;
/*       */     String acctName;
/*  1024 */     if (handlerConfig != null)
/*       */     {
/*  1026 */       acctName = DomainNameMappingHandler.mapName(handlerConfig, foreignName, domain.getName());
/*       */     }
/*       */     else {
/*  1029 */       acctName = foreignName.split("@")[0] + "@" + domain.getName();
/*       */     }
/*       */     
/*  1032 */     return get(Key.AccountBy.name, acctName);
/*       */   }
/*       */   
/*       */   private Cos lookupCos(String key, ZLdapContext zlc) throws ServiceException {
/*  1036 */     Cos c = null;
/*  1037 */     c = getCosById(key, zlc);
/*  1038 */     if (c == null)
/*  1039 */       c = getCosByName(key, zlc);
/*  1040 */     if (c == null) {
/*  1041 */       throw AccountServiceException.NO_SUCH_COS(key);
/*       */     }
/*  1043 */     return c;
/*       */   }
/*       */   
/*       */   public void autoProvAccountEager(Provisioning.EagerAutoProvisionScheduler scheduler)
/*       */     throws ServiceException
/*       */   {
/*  1049 */     AutoProvisionEager.handleScheduledDomains(this, scheduler);
/*       */   }
/*       */   
/*       */ 
/*       */   public Account autoProvAccountLazy(Domain domain, String loginName, String loginPassword, ZAttrProvisioning.AutoProvAuthMech authMech)
/*       */     throws ServiceException
/*       */   {
/*  1056 */     AutoProvisionLazy autoPorv = new AutoProvisionLazy(this, domain, loginName, loginPassword, authMech);
/*       */     
/*  1058 */     return autoPorv.handle();
/*       */   }
/*       */   
/*       */ 
/*       */   public Account autoProvAccountManual(Domain domain, AutoProvPrincipalBy by, String principal, String password)
/*       */     throws ServiceException
/*       */   {
/*  1065 */     AutoProvisionManual autoProv = new AutoProvisionManual(this, domain, by, principal, password);
/*       */     
/*  1067 */     return autoProv.handle();
/*       */   }
/*       */   
/*       */ 
/*       */   public void searchAutoProvDirectory(Domain domain, String filter, String name, String[] returnAttrs, int maxResults, Provisioning.DirectoryEntryVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  1074 */     AutoProvision.searchAutoProvDirectory(this, domain, filter, name, null, returnAttrs, maxResults, visitor);
/*       */   }
/*       */   
/*       */ 
/*       */   public Account createAccount(String emailAddress, String password, Map<String, Object> attrs)
/*       */     throws ServiceException
/*       */   {
/*  1081 */     return createAccount(emailAddress, password, attrs, this.mDIT.handleSpecialAttrs(attrs), null, false, null);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public Account restoreAccount(String emailAddress, String password, Map<String, Object> attrs, Map<String, Object> origAttrs)
/*       */     throws ServiceException
/*       */   {
/*  1089 */     return createAccount(emailAddress, password, attrs, this.mDIT.handleSpecialAttrs(attrs), null, true, origAttrs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private Account createAccount(String emailAddress, String password, Map<String, Object> acctAttrs, SpecialAttrs specialAttrs, String[] additionalObjectClasses, boolean restoring, Map<String, Object> origAttrs)
/*       */     throws ServiceException
/*       */   {
/*  1099 */     String uuid = specialAttrs.getZimbraId();
/*  1100 */     String baseDn = specialAttrs.getLdapBaseDn();
/*       */     
/*  1102 */     emailAddress = emailAddress.toLowerCase().trim();
/*  1103 */     String[] parts = emailAddress.split("@");
/*  1104 */     if (parts.length != 2) {
/*  1105 */       throw ServiceException.INVALID_REQUEST("must be valid email address: " + emailAddress, null);
/*       */     }
/*       */     
/*       */ 
/*  1109 */     String localPart = parts[0];
/*  1110 */     String domain = parts[1];
/*  1111 */     domain = IDNUtil.toAsciiDomainName(domain);
/*  1112 */     emailAddress = localPart + "@" + domain;
/*       */     
/*  1114 */     validEmailAddress(emailAddress);
/*       */     
/*  1116 */     if (restoring) {
/*  1117 */       validate("createAccount", new Object[] { emailAddress, additionalObjectClasses, origAttrs });
/*       */       
/*  1119 */       validate("createAccountCheckDomainCosAndFeature", new Object[] { emailAddress, origAttrs });
/*       */     }
/*       */     else {
/*  1122 */       validate("createAccount", new Object[] { emailAddress, additionalObjectClasses, acctAttrs });
/*       */       
/*  1124 */       validate("createAccountCheckDomainCosAndFeature", new Object[] { emailAddress, acctAttrs });
/*       */     }
/*       */     
/*       */ 
/*  1128 */     if (acctAttrs == null) {
/*  1129 */       acctAttrs = new HashMap();
/*       */     }
/*  1131 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  1132 */     callbackContext.setCreatingEntryName(emailAddress);
/*  1133 */     AttributeManager.getInstance().preModify(acctAttrs, null, callbackContext, true);
/*       */     
/*  1135 */     Account acct = null;
/*  1136 */     String dn = null;
/*  1137 */     ZLdapContext zlc = null;
/*       */     try {
/*  1139 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_ACCOUNT);
/*       */       
/*  1141 */       Domain d = getDomainByAsciiName(domain, zlc);
/*  1142 */       if (d == null) {
/*  1143 */         throw AccountServiceException.NO_SUCH_DOMAIN(domain);
/*       */       }
/*       */       
/*  1146 */       if (!d.isLocal()) {
/*  1147 */         throw ServiceException.INVALID_REQUEST("domain type must be local", null);
/*       */       }
/*       */       
/*  1150 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  1151 */       entry.mapToAttrs(acctAttrs);
/*       */       
/*  1153 */       for (int i = 0; i < sInvalidAccountCreateModifyAttrs.length; i++) {
/*  1154 */         String a = sInvalidAccountCreateModifyAttrs[i];
/*  1155 */         if (entry.hasAttribute(a))
/*  1156 */           throw ServiceException.INVALID_REQUEST("invalid attribute for CreateAccount: " + a, null);
/*       */       }
/*       */       Set<String> ocs;
/*       */       Set<String> ocs;
/*  1160 */       if (additionalObjectClasses == null)
/*       */       {
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1168 */         ocs = LdapObjectClass.getAccountObjectClasses(this, restoring);
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */       }
/*       */       else
/*       */       {
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1189 */         ocs = LdapObjectClass.getAccountObjectClasses(this, true);
/*  1190 */         for (int i = 0; i < additionalObjectClasses.length; i++) {
/*  1191 */           ocs.add(additionalObjectClasses[i]);
/*       */         }
/*       */       }
/*  1194 */       boolean skipCountingLicenseQuota = false;
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1202 */       if ((restoring) && (origAttrs != null)) {
/*  1203 */         Object ocsInBackupObj = origAttrs.get("objectClass");
/*  1204 */         String[] ocsInBackup = StringUtil.toStringArray(ocsInBackupObj);
/*       */         
/*  1206 */         String mostSpecificOC = LdapObjectClassHierarchy.getMostSpecificOC(this, ocsInBackup, LdapObjectClass.ZIMBRA_DEFAULT_PERSON_OC);
/*       */         
/*       */ 
/*  1209 */         if (!LdapObjectClass.ZIMBRA_DEFAULT_PERSON_OC.equalsIgnoreCase(mostSpecificOC)) {
/*  1210 */           ocs.add(mostSpecificOC);
/*       */         }
/*       */         
/*       */ 
/*  1214 */         if (origAttrs.get("zimbraCalResType") != null) {
/*  1215 */           skipCountingLicenseQuota = true;
/*       */         }
/*  1217 */         if (origAttrs.get("zimbraIsSystemResource") != null) {
/*  1218 */           entry.setAttr("zimbraIsSystemResource", "TRUE");
/*  1219 */           skipCountingLicenseQuota = true;
/*       */         }
/*  1221 */         if (origAttrs.get("zimbraIsExternalVirtualAccount") != null) {
/*  1222 */           entry.setAttr("zimbraIsExternalVirtualAccount", "TRUE");
/*  1223 */           skipCountingLicenseQuota = true;
/*       */         }
/*       */       }
/*       */       
/*  1227 */       entry.addAttr("objectClass", ocs);
/*       */       String zimbraIdStr;
/*       */       String zimbraIdStr;
/*  1230 */       if (uuid == null) {
/*  1231 */         zimbraIdStr = LdapUtil.generateUUID();
/*       */       } else {
/*  1233 */         zimbraIdStr = uuid;
/*       */       }
/*  1235 */       entry.setAttr("zimbraId", zimbraIdStr);
/*  1236 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*       */       
/*       */ 
/*  1239 */       if (!entry.hasAttribute("zimbraAccountStatus")) {
/*  1240 */         entry.setAttr("zimbraAccountStatus", "active");
/*       */       }
/*       */       
/*  1243 */       Cos cos = null;
/*  1244 */       String cosId = entry.getAttrString("zimbraCOSId");
/*       */       
/*  1246 */       if (cosId != null) {
/*  1247 */         cos = lookupCos(cosId, zlc);
/*  1248 */         if (!cos.getId().equals(cosId)) {
/*  1249 */           cosId = cos.getId();
/*       */         }
/*  1251 */         entry.setAttr("zimbraCOSId", cosId);
/*       */       } else {
/*  1253 */         String domainCosId = domain != null ? d.getDomainDefaultCOSId() : isExternalVirtualAccount(entry) ? d.getDomainDefaultExternalUserCOSId() : null;
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1260 */         if (domainCosId != null) {
/*  1261 */           cos = get(Key.CosBy.id, domainCosId);
/*       */         }
/*  1263 */         if (cos == null) {
/*  1264 */           cos = getCosByName(isExternalVirtualAccount(entry) ? "defaultExternal" : "default", zlc);
/*       */         }
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  1270 */       boolean hasMailTransport = entry.hasAttribute("zimbraMailTransport");
/*       */       
/*       */ 
/*       */ 
/*  1274 */       if (!hasMailTransport) {
/*  1275 */         addMailHost(entry, cos, true);
/*       */       }
/*       */       
/*       */ 
/*  1279 */       if ((entry.hasAttribute("zimbraMailHost")) || (entry.hasAttribute("zimbraMailTransport")))
/*       */       {
/*       */ 
/*  1282 */         if (!entry.hasAttribute("zimbraMailStatus")) {
/*  1283 */           entry.setAttr("zimbraMailStatus", "enabled");
/*       */         }
/*       */         
/*       */ 
/*  1287 */         if (!entry.hasAttribute("zimbraMailDeliveryAddress")) {
/*  1288 */           entry.setAttr("zimbraMailDeliveryAddress", emailAddress);
/*       */         }
/*       */       } else {
/*  1291 */         throw ServiceException.INVALID_REQUEST("missing zimbraMailHost or zimbraMailTransport for CreateAccount: " + emailAddress, null);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  1297 */       entry.setAttr("mail", emailAddress);
/*       */       
/*       */ 
/*  1300 */       if (!entry.hasAttribute("cn")) {
/*  1301 */         String displayName = entry.getAttrString("displayName");
/*  1302 */         if (displayName != null) {
/*  1303 */           entry.setAttr("cn", displayName);
/*       */         } else {
/*  1305 */           entry.setAttr("cn", localPart);
/*       */         }
/*       */       }
/*       */       
/*       */ 
/*  1310 */       if (!entry.hasAttribute("sn")) {
/*  1311 */         entry.setAttr("sn", localPart);
/*       */       }
/*       */       
/*  1314 */       entry.setAttr("uid", localPart);
/*  1315 */       String entryPassword = entry.getAttrString("userPassword");
/*  1316 */       if (entryPassword != null)
/*       */       {
/*  1318 */         password = null;
/*  1319 */       } else if (password != null)
/*       */       {
/*  1321 */         checkPasswordStrength(password, null, cos, entry);
/*       */       }
/*  1323 */       entry.setAttr("zimbraPasswordModifiedTime", DateUtil.toGeneralizedTime(new Date()));
/*       */       
/*  1325 */       String ucPassword = entry.getAttrString("zimbraUCPassword");
/*  1326 */       String encryptedPassword; if (ucPassword != null) {
/*  1327 */         encryptedPassword = Account.encrypytUCPassword(entry.getAttrString("zimbraId"), ucPassword);
/*       */         
/*  1329 */         entry.setAttr("zimbraUCPassword", encryptedPassword);
/*       */       }
/*       */       
/*  1332 */       dn = this.mDIT.accountDNCreate(baseDn, entry.getAttributes(), localPart, domain);
/*  1333 */       entry.setDN(dn);
/*       */       
/*  1335 */       zlc.createEntry(entry);
/*  1336 */       acct = getAccountById(zimbraIdStr, zlc, true);
/*  1337 */       if (acct == null) {
/*  1338 */         throw ServiceException.FAILURE("unable to get account after creating LDAP account entry: " + emailAddress + ", check ldap log for possible error", null);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  1343 */       AttributeManager.getInstance().postModify(acctAttrs, acct, callbackContext);
/*  1344 */       removeExternalAddrsFromAllDynamicGroups(acct.getAllAddrsSet(), zlc);
/*  1345 */       validate("createAccountSucceeded", new Object[] { emailAddress, acct, Boolean.valueOf(skipCountingLicenseQuota) });
/*  1346 */       if (password != null)
/*  1347 */         setLdapPassword(acct, zlc, password);
/*       */       Iterator i$;
/*  1349 */       ProvisioningExt.PostCreateAccountListener listener; return acct;
/*       */     } catch (LdapException.LdapEntryAlreadyExistException e) {
/*  1351 */       throw AccountServiceException.ACCOUNT_EXISTS(emailAddress, dn, e);
/*       */     } catch (LdapException e) {
/*  1353 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  1355 */       throw e;
/*       */     } catch (ServiceException e) {
/*  1357 */       throw ServiceException.FAILURE("unable to create account: " + emailAddress, e);
/*       */     } finally {
/*  1359 */       LdapClient.closeContext(zlc);
/*       */       
/*  1361 */       if ((!restoring) && (acct != null)) {
/*  1362 */         for (ProvisioningExt.PostCreateAccountListener listener : com.zimbra.cs.account.ProvisioningExt.getPostCreateAccountListeners()) {
/*  1363 */           if (listener.enabled()) {
/*  1364 */             listener.handle(acct);
/*       */           }
/*       */         }
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   private boolean isExternalVirtualAccount(ZMutableEntry entry) throws LdapException {
/*  1372 */     return (entry.hasAttribute("zimbraIsExternalVirtualAccount")) && ("TRUE".equals(entry.getAttrString("zimbraIsExternalVirtualAccount")));
/*       */   }
/*       */   
/*       */ 
/*       */   public void searchOCsForSuperClasses(Map<String, Set<String>> ocs)
/*       */   {
/*  1378 */     ZLdapContext zlc = null;
/*       */     try {
/*  1380 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.GET_SCHEMA);
/*  1381 */       schema = zlc.getSchema();
/*       */       
/*  1383 */       for (Map.Entry<String, Set<String>> entry : ocs.entrySet()) {
/*  1384 */         String oc = (String)entry.getKey();
/*  1385 */         Set<String> superOCs = (Set)entry.getValue();
/*       */         try
/*       */         {
/*  1388 */           ZimbraLog.account.debug("Looking up OC: " + oc);
/*  1389 */           ZLdapSchema.ZObjectClassDefinition ocSchema = schema.getObjectClass(oc);
/*       */           
/*  1391 */           if (ocSchema != null) {
/*  1392 */             List<String> superClasses = ocSchema.getSuperiorClasses();
/*  1393 */             for (String superOC : superClasses) {
/*  1394 */               superOCs.add(superOC.toLowerCase());
/*       */             }
/*       */           }
/*       */         }
/*       */         catch (ServiceException e) {
/*  1399 */           ZimbraLog.account.debug("unable to load LDAP schema extension for objectclass: " + oc, e);
/*       */         }
/*       */       }
/*       */     }
/*       */     catch (ServiceException e) {
/*       */       ZLdapSchema schema;
/*  1405 */       ZimbraLog.account.warn("unable to get LDAP schema", e);
/*       */     } finally {
/*  1407 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public void getAttrsInOCs(String[] ocs, Set<String> attrsInOCs)
/*       */     throws ServiceException
/*       */   {
/*  1416 */     ZLdapContext zlc = null;
/*       */     try {
/*  1418 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.GET_SCHEMA);
/*  1419 */       ZLdapSchema schema = zlc.getSchema();
/*       */       
/*  1421 */       for (String oc : ocs) {
/*       */         try {
/*  1423 */           ZLdapSchema.ZObjectClassDefinition ocSchema = schema.getObjectClass(oc);
/*       */           
/*  1425 */           if (ocSchema != null) {
/*  1426 */             List<String> optAttrs = ocSchema.getOptionalAttributes();
/*  1427 */             for (String attr : optAttrs) {
/*  1428 */               attrsInOCs.add(attr);
/*       */             }
/*  1430 */             List<String> reqAttrs = ocSchema.getRequiredAttributes();
/*  1431 */             for (String attr : reqAttrs) {
/*  1432 */               attrsInOCs.add(attr);
/*       */             }
/*       */           }
/*       */         }
/*       */         catch (ServiceException e) {
/*  1437 */           ZimbraLog.account.debug("unable to lookup attributes for objectclass: " + oc, e);
/*       */         }
/*       */       }
/*       */     }
/*       */     catch (ServiceException e) {
/*  1442 */       ZimbraLog.account.warn("unable to get LDAP schema", e);
/*       */     } finally {
/*  1444 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   private void setMailHost(ZMutableEntry entry, Server server, boolean setMailTransport) {
/*  1449 */     String serviceHostname = server.getAttr("zimbraServiceHostname");
/*  1450 */     entry.setAttr("zimbraMailHost", serviceHostname);
/*       */     
/*  1452 */     if (setMailTransport) {
/*  1453 */       int lmtpPort = server.getIntAttr("zimbraLmtpBindPort", 7025);
/*       */       
/*  1455 */       String transport = "lmtp:" + serviceHostname + ":" + lmtpPort;
/*  1456 */       entry.setAttr("zimbraMailTransport", transport);
/*       */     }
/*       */   }
/*       */   
/*       */   private boolean addDefaultMailHost(ZMutableEntry entry, Server server, boolean setMailTransport) throws ServiceException
/*       */   {
/*  1462 */     String serviceHostname = server.getAttr("zimbraServiceHostname");
/*  1463 */     if ((server.hasMailClientService()) && (serviceHostname != null)) {
/*  1464 */       setMailHost(entry, server, setMailTransport);
/*  1465 */       return true;
/*       */     }
/*  1467 */     return false;
/*       */   }
/*       */   
/*       */   private void addDefaultMailHost(ZMutableEntry entry, boolean setMailTransport) throws ServiceException
/*       */   {
/*  1472 */     if (!addDefaultMailHost(entry, getLocalServer(), setMailTransport)) {
/*  1473 */       for (Server server : getAllServers()) {
/*  1474 */         if (addDefaultMailHost(entry, server, setMailTransport)) {
/*  1475 */           return;
/*       */         }
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   private void addMailHost(ZMutableEntry entry, Cos cos, boolean setMailTransport)
/*       */     throws ServiceException
/*       */   {
/*  1485 */     if ((cos != null) && (!entry.hasAttribute("zimbraMailHost"))) {
/*  1486 */       String[] mailHostPool = cos.getMultiAttr("zimbraMailHostPool");
/*  1487 */       addMailHost(entry, mailHostPool, cos.getName(), setMailTransport);
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1494 */     if (!entry.hasAttribute("zimbraMailHost")) {
/*  1495 */       addDefaultMailHost(entry, setMailTransport);
/*       */     }
/*       */   }
/*       */   
/*       */   private String addMailHost(ZMutableEntry entry, String[] mailHostPool, String cosName, boolean setMailTransport)
/*       */     throws ServiceException
/*       */   {
/*  1502 */     if (mailHostPool.length == 0)
/*  1503 */       return null;
/*  1504 */     if (mailHostPool.length > 1)
/*       */     {
/*  1506 */       String[] pool = new String[mailHostPool.length];
/*  1507 */       System.arraycopy(mailHostPool, 0, pool, 0, mailHostPool.length);
/*  1508 */       mailHostPool = pool;
/*       */     }
/*       */     
/*       */ 
/*  1512 */     int max = mailHostPool.length;
/*  1513 */     while (max > 0) {
/*  1514 */       int i = sPoolRandom.nextInt(max);
/*  1515 */       String mailHostId = mailHostPool[i];
/*  1516 */       Server s = mailHostId == null ? null : getServerByIdInternal(mailHostId);
/*  1517 */       if (s != null) {
/*  1518 */         String mailHost = s.getAttr("zimbraServiceHostname");
/*  1519 */         if (mailHost != null) {
/*  1520 */           if (s.hasMailClientService()) {
/*  1521 */             setMailHost(entry, s, setMailTransport);
/*  1522 */             return mailHost;
/*       */           }
/*  1524 */           ZimbraLog.account.warn("cos(" + cosName + ") mailHostPool server(" + s.getName() + ") is not a mailclient server with service webapp enabled");
/*       */         }
/*       */         else
/*       */         {
/*  1528 */           ZimbraLog.account.warn("cos(" + cosName + ") mailHostPool server(" + s.getName() + ") has no service hostname");
/*       */         }
/*       */       }
/*       */       else {
/*  1532 */         ZimbraLog.account.warn("cos(" + cosName + ") has invalid server in pool: " + mailHostId);
/*       */       }
/*  1534 */       if (i != max - 1) {
/*  1535 */         mailHostPool[i] = mailHostPool[(max - 1)];
/*       */       }
/*  1537 */       max--;
/*       */     }
/*  1539 */     return null;
/*       */   }
/*       */   
/*       */   public List<Account> getAllAdminAccounts()
/*       */     throws ServiceException
/*       */   {
/*  1545 */     SearchAccountsOptions opts = new SearchAccountsOptions();
/*  1546 */     opts.setFilter(this.filterFactory.allAdminAccounts());
/*  1547 */     opts.setIncludeType(SearchAccountsOptions.IncludeType.ACCOUNTS_ONLY);
/*  1548 */     opts.setSortOpt(SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*  1549 */     return searchDirectoryInternal(opts);
/*       */   }
/*       */   
/*       */ 
/*       */   public void searchAccountsOnServer(Server server, SearchAccountsOptions opts, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  1556 */     searchAccountsOnServerInternal(server, opts, visitor);
/*       */   }
/*       */   
/*       */   public List<NamedEntry> searchAccountsOnServer(Server server, SearchAccountsOptions opts)
/*       */     throws ServiceException
/*       */   {
/*  1562 */     return searchAccountsOnServerInternal(server, opts, null);
/*       */   }
/*       */   
/*       */ 
/*       */   private List<NamedEntry> searchAccountsOnServerInternal(Server server, SearchAccountsOptions options, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  1569 */     if ((options.getFilter() != null) || (options.getFilterString() != null)) {
/*  1570 */       throw ServiceException.INVALID_REQUEST("cannot set filter for searchAccountsOnServer", null);
/*       */     }
/*       */     
/*       */ 
/*  1574 */     if (server == null) {
/*  1575 */       throw ServiceException.INVALID_REQUEST("missing server", null);
/*       */     }
/*       */     
/*       */ 
/*  1579 */     SearchAccountsOptions.IncludeType includeType = options.getIncludeType();
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1589 */     Domain domain = options.getDomain();
/*       */     ZLdapFilter filter;
/*  1591 */     ZLdapFilter filter; if (includeType == SearchAccountsOptions.IncludeType.ACCOUNTS_AND_CALENDAR_RESOURCES) {
/*  1592 */       filter = this.mDIT.filterAccountsByDomainAndServer(domain, server); } else { ZLdapFilter filter;
/*  1593 */       if (includeType == SearchAccountsOptions.IncludeType.ACCOUNTS_ONLY) {
/*  1594 */         filter = this.mDIT.filterAccountsOnlyByDomainAndServer(domain, server);
/*       */       } else {
/*  1596 */         filter = this.mDIT.filterCalendarResourceByDomainAndServer(domain, server);
/*       */       }
/*       */     }
/*  1599 */     options.setFilter(filter);
/*  1600 */     return searchDirectoryInternal(options, visitor);
/*       */   }
/*       */   
/*       */   public List<NamedEntry> searchDirectory(SearchDirectoryOptions options)
/*       */     throws ServiceException
/*       */   {
/*  1606 */     return searchDirectoryInternal(options, null);
/*       */   }
/*       */   
/*       */   public void searchDirectory(SearchDirectoryOptions options, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  1612 */     searchDirectoryInternal(options, visitor);
/*       */   }
/*       */   
/*       */   protected List<?> searchDirectoryInternal(SearchDirectoryOptions options) throws ServiceException
/*       */   {
/*  1617 */     return searchDirectoryInternal(options, null);
/*       */   }
/*       */   
/*       */   public String[] getSearchBases(Domain domain, Set<SearchDirectoryOptions.ObjectType> types) throws ServiceException
/*       */   {
/*       */     String[] bases;
/*       */     String[] bases;
/*  1624 */     if (domain != null) {
/*  1625 */       String domainDN = ((LdapDomain)domain).getDN();
/*       */       
/*  1627 */       boolean domainsTree = false;
/*  1628 */       boolean groupsTree = false;
/*  1629 */       boolean peopleTree = false;
/*       */       
/*  1631 */       if (types.contains(SearchDirectoryOptions.ObjectType.dynamicgroups)) {
/*  1632 */         groupsTree = true;
/*       */       }
/*  1634 */       if ((types.contains(SearchDirectoryOptions.ObjectType.accounts)) || (types.contains(SearchDirectoryOptions.ObjectType.aliases)) || (types.contains(SearchDirectoryOptions.ObjectType.distributionlists)) || (types.contains(SearchDirectoryOptions.ObjectType.resources)))
/*       */       {
/*       */ 
/*       */ 
/*  1638 */         peopleTree = true;
/*       */       }
/*  1640 */       if (types.contains(SearchDirectoryOptions.ObjectType.domains)) {
/*  1641 */         domainsTree = true;
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  1647 */       if ((!groupsTree) && (!peopleTree) && (!domainsTree)) {
/*  1648 */         throw ServiceException.INVALID_REQUEST("domain is specified but non of domain-ed types is specified", null);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1665 */       if ((domainsTree) && ((groupsTree) || (peopleTree))) {
/*  1666 */         throw ServiceException.FAILURE("specifying domains type and one of accounts/resources/groups type is not supported by in-memory LDAP server", null);
/*       */       }
/*       */       
/*       */ 
/*       */       String[] bases;
/*       */       
/*       */ 
/*  1673 */       if (InMemoryLdapServer.isOn())
/*       */       {
/*       */         String[] bases;
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1684 */         if (domainsTree) {
/*  1685 */           bases = new String[] { domainDN };
/*       */         } else {
/*  1687 */           List<String> baseList = Lists.newArrayList();
/*       */           
/*  1689 */           if (groupsTree) {
/*  1690 */             baseList.add(this.mDIT.domainDNToDynamicGroupsBaseDN(domainDN));
/*       */           }
/*       */           
/*  1693 */           if (peopleTree) {
/*  1694 */             baseList.add(this.mDIT.domainDNToAccountSearchDN(domainDN));
/*       */           }
/*       */           
/*  1697 */           bases = (String[])baseList.toArray(new String[baseList.size()]);
/*       */         }
/*       */       }
/*       */       else
/*       */       {
/*       */         String searchBase;
/*       */         
/*       */ 
/*       */         String searchBase;
/*       */         
/*       */ 
/*  1708 */         if (domainsTree) {
/*  1709 */           searchBase = domainDN;
/*       */         } else { String searchBase;
/*  1711 */           if ((groupsTree) && (peopleTree)) {
/*  1712 */             searchBase = domainDN; } else { String searchBase;
/*  1713 */             if (groupsTree) {
/*  1714 */               searchBase = this.mDIT.domainDNToDynamicGroupsBaseDN(domainDN);
/*       */             } else
/*  1716 */               searchBase = this.mDIT.domainDNToAccountSearchDN(domainDN);
/*       */           }
/*       */         }
/*  1719 */         bases = new String[] { searchBase };
/*       */       }
/*       */     }
/*       */     else {
/*  1723 */       int flags = SearchDirectoryOptions.getTypesAsFlags(types);
/*  1724 */       bases = this.mDIT.getSearchBases(flags);
/*       */     }
/*       */     
/*  1727 */     return bases;
/*       */   }
/*       */   
/*       */   private List<NamedEntry> searchDirectoryInternal(SearchDirectoryOptions options, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  1733 */     Set<SearchDirectoryOptions.ObjectType> types = options.getTypes();
/*       */     
/*  1735 */     if (types == null) {
/*  1736 */       throw ServiceException.INVALID_REQUEST("missing types", null);
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  1742 */     Domain domain = options.getDomain();
/*  1743 */     String[] bases = getSearchBases(domain, types);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  1748 */     int flags = options.getTypesAsFlags();
/*  1749 */     ZLdapFilter filter = options.getFilter();
/*  1750 */     String filterStr = options.getFilterString();
/*       */     
/*       */ 
/*  1753 */     if ((filter != null) && (filterStr != null)) {
/*  1754 */       throw ServiceException.INVALID_REQUEST("only one of filter or filterString can be set", null);
/*       */     }
/*       */     
/*  1757 */     if (filter == null) {
/*  1758 */       if ((options.getConvertIDNToAscii()) && (!Strings.isNullOrEmpty(filterStr))) {
/*  1759 */         filterStr = LdapEntrySearchFilter.toLdapIDNFilter(filterStr);
/*       */       }
/*       */       
/*       */ 
/*  1763 */       String objectClass = getObjectClassQuery(flags);
/*       */       
/*  1765 */       if ((filterStr == null) || (filterStr.equals(""))) {
/*  1766 */         filterStr = objectClass;
/*       */       }
/*  1768 */       else if ((filterStr.startsWith("(")) && (filterStr.endsWith(")"))) {
/*  1769 */         filterStr = "(&" + objectClass + filterStr + ")";
/*       */       } else {
/*  1771 */         filterStr = "(&" + objectClass + "(" + filterStr + ")" + ")";
/*       */       }
/*       */       
/*       */ 
/*  1775 */       ZLdapFilterFactory.FilterId filterId = options.getFilterId();
/*  1776 */       if (filterId == null) {
/*  1777 */         throw ServiceException.INVALID_REQUEST("missing filter id", null);
/*       */       }
/*  1779 */       filter = this.filterFactory.fromFilterString(options.getFilterId(), filterStr);
/*       */     }
/*       */     
/*  1782 */     if ((domain != null) && (!InMemoryLdapServer.isOn())) {
/*  1783 */       boolean groupsTree = false;
/*  1784 */       boolean peopleTree = false;
/*       */       
/*  1786 */       if (types.contains(SearchDirectoryOptions.ObjectType.dynamicgroups)) {
/*  1787 */         groupsTree = true;
/*       */       }
/*  1789 */       if ((types.contains(SearchDirectoryOptions.ObjectType.accounts)) || (types.contains(SearchDirectoryOptions.ObjectType.aliases)) || (types.contains(SearchDirectoryOptions.ObjectType.distributionlists)) || (types.contains(SearchDirectoryOptions.ObjectType.resources)))
/*       */       {
/*       */ 
/*       */ 
/*  1793 */         peopleTree = true;
/*       */       }
/*       */       
/*  1796 */       if ((groupsTree) && (peopleTree)) {
/*  1797 */         ZLdapFilter dnSubtreeMatchFilter = ((LdapDomain)domain).getDnSubtreeMatchFilter();
/*  1798 */         filter = this.filterFactory.andWith(filter, dnSubtreeMatchFilter);
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1806 */     String[] returnAttrs = fixReturnAttrs(options.getReturnAttrs(), flags);
/*       */     
/*  1808 */     return searchObjects(bases, filter, returnAttrs, options, visitor);
/*       */   }
/*       */   
/*       */   private static String getObjectClassQuery(int flags) {
/*  1812 */     boolean accounts = (flags & 0x1) != 0;
/*  1813 */     boolean aliases = (flags & 0x2) != 0;
/*  1814 */     boolean lists = (flags & 0x4) != 0;
/*  1815 */     boolean groups = (flags & 0x100) != 0;
/*  1816 */     boolean calendarResources = (flags & 0x8) != 0;
/*  1817 */     boolean domains = (flags & 0x10) != 0;
/*  1818 */     boolean coses = (flags & 0x20) != 0;
/*       */     
/*  1820 */     int num = (accounts ? 1 : 0) + (aliases ? 1 : 0) + (lists ? 1 : 0) + (groups ? 1 : 0) + (domains ? 1 : 0) + (coses ? 1 : 0) + (calendarResources ? 1 : 0);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1827 */     if (num == 0) {
/*  1828 */       accounts = true;
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  1842 */     StringBuffer oc = new StringBuffer();
/*       */     
/*  1844 */     if ((accounts) && (!calendarResources)) {
/*  1845 */       oc.append("(&");
/*       */     }
/*       */     
/*  1848 */     if (num > 1) {
/*  1849 */       oc.append("(|");
/*       */     }
/*       */     
/*  1852 */     if (accounts) oc.append("(objectclass=zimbraAccount)");
/*  1853 */     if (aliases) oc.append("(objectclass=zimbraAlias)");
/*  1854 */     if (lists) oc.append("(objectclass=zimbraDistributionList)");
/*  1855 */     if (groups) oc.append("(objectclass=zimbraGroup)");
/*  1856 */     if (domains) oc.append("(objectclass=zimbraDomain)");
/*  1857 */     if (coses) oc.append("(objectclass=zimbraCos)");
/*  1858 */     if (calendarResources) { oc.append("(objectclass=zimbraCalendarResource)");
/*       */     }
/*  1860 */     if (num > 1) {
/*  1861 */       oc.append(")");
/*       */     }
/*       */     
/*  1864 */     if ((accounts) && (!calendarResources)) {
/*  1865 */       oc.append("(!(objectclass=zimbraCalendarResource)))");
/*       */     }
/*       */     
/*  1868 */     return oc.toString();
/*       */   }
/*       */   
/*       */   private static class NamedEntryComparator implements Comparator<NamedEntry> {
/*       */     final Provisioning mProv;
/*       */     final String mSortAttr;
/*       */     final boolean mSortAscending;
/*       */     final boolean mByName;
/*       */     
/*       */     NamedEntryComparator(Provisioning prov, String sortAttr, boolean sortAscending) {
/*  1878 */       this.mProv = prov;
/*  1879 */       this.mSortAttr = sortAttr;
/*  1880 */       this.mSortAscending = sortAscending;
/*  1881 */       this.mByName = ((sortAttr == null) || (sortAttr.length() == 0) || (sortAttr.equals("name")));
/*       */     }
/*       */     
/*       */     public int compare(NamedEntry a, NamedEntry b)
/*       */     {
/*  1886 */       int comp = 0;
/*       */       
/*  1888 */       if (this.mByName) {
/*  1889 */         comp = a.getName().compareToIgnoreCase(b.getName());
/*       */       } else {
/*  1891 */         String sa = null;
/*  1892 */         String sb = null;
/*  1893 */         if (("targetName".equals(this.mSortAttr)) && ((a instanceof Alias)) && ((b instanceof Alias)))
/*       */         {
/*       */           try {
/*  1896 */             sa = ((Alias)a).getTargetUnicodeName(this.mProv);
/*       */           } catch (ServiceException e) {
/*  1898 */             ZimbraLog.account.error("unable to get target name: " + a.getName(), e);
/*       */           }
/*       */           try {
/*  1901 */             sb = ((Alias)b).getTargetUnicodeName(this.mProv);
/*       */           } catch (ServiceException e) {
/*  1903 */             ZimbraLog.account.error("unable to get target name: " + b.getName(), e);
/*       */           }
/*       */         }
/*       */         else {
/*  1907 */           sa = a.getAttr(this.mSortAttr);
/*  1908 */           sb = b.getAttr(this.mSortAttr);
/*       */         }
/*  1910 */         if (sa == null) sa = "";
/*  1911 */         if (sb == null) sb = "";
/*  1912 */         comp = sa.compareToIgnoreCase(sb);
/*       */       }
/*  1914 */       return this.mSortAscending ? comp : -comp;
/*       */     }
/*       */   }
/*       */   
/*       */   @LdapTODO.TODO
/*       */   private static class SearchObjectsVisitor
/*       */     extends SearchLdapOptions.SearchLdapVisitor
/*       */   {
/*       */     private final LdapProvisioning prov;
/*       */     private final ZLdapContext zlc;
/*       */     private final String configBranchBaseDn;
/*       */     private final NamedEntry.Visitor visitor;
/*       */     private final int maxResults;
/*       */     private final SearchDirectoryOptions.MakeObjectOpt makeObjOpt;
/*       */     private final String[] returnAttrs;
/*  1929 */     private final int total = 0;
/*       */     
/*       */ 
/*       */     private SearchObjectsVisitor(LdapProvisioning prov, ZLdapContext zlc, NamedEntry.Visitor visitor, int maxResults, SearchDirectoryOptions.MakeObjectOpt makeObjOpt, String[] returnAttrs)
/*       */     {
/*  1934 */       super();
/*       */       
/*  1936 */       this.prov = prov;
/*  1937 */       this.zlc = zlc;
/*  1938 */       this.configBranchBaseDn = prov.getDIT().configBranchBaseDN();
/*  1939 */       this.visitor = visitor;
/*  1940 */       this.maxResults = maxResults;
/*  1941 */       this.makeObjOpt = makeObjOpt;
/*  1942 */       this.returnAttrs = returnAttrs;
/*       */     }
/*       */     
/*       */     public void visit(String dn, IAttributes ldapAttrs)
/*       */     {
/*       */       try {
/*  1948 */         doVisit(dn, ldapAttrs);
/*       */       } catch (ServiceException e) {
/*  1950 */         ZimbraLog.account.warn("entry skipped, encountered error while processing entry at:" + dn, e);
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */     @LdapTODO.TODO
/*       */     private void doVisit(String dn, IAttributes ldapAttrs)
/*       */       throws ServiceException
/*       */     {
/*  1962 */       List<String> objectclass = ldapAttrs.getMultiAttrStringAsList("objectClass", IAttributes.CheckBinary.NOCHECK);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  1967 */       if ((dn.endsWith(this.configBranchBaseDn)) && (!objectclass.contains(AttributeClass.OC_zimbraDomain)) && (!objectclass.contains(AttributeClass.OC_zimbraCOS)))
/*       */       {
/*       */ 
/*  1970 */         return;
/*       */       }
/*       */       
/*  1973 */       ZAttributes attrs = (ZAttributes)ldapAttrs;
/*       */       
/*  1975 */       if ((objectclass == null) || (objectclass.contains(AttributeClass.OC_zimbraAccount))) {
/*  1976 */         this.visitor.visit(this.prov.makeAccount(dn, attrs, this.makeObjOpt));
/*  1977 */       } else if (objectclass.contains(AttributeClass.OC_zimbraAlias)) {
/*  1978 */         this.visitor.visit(this.prov.makeAlias(dn, attrs));
/*  1979 */       } else if (objectclass.contains(AttributeClass.OC_zimbraDistributionList)) {
/*  1980 */         boolean isBasic = this.returnAttrs != null;
/*  1981 */         this.visitor.visit(this.prov.makeDistributionList(dn, attrs, isBasic));
/*  1982 */       } else if (objectclass.contains(AttributeClass.OC_zimbraGroup)) {
/*  1983 */         this.visitor.visit(this.prov.makeDynamicGroup(this.zlc, dn, attrs));
/*  1984 */       } else if (objectclass.contains(AttributeClass.OC_zimbraDomain)) {
/*  1985 */         this.visitor.visit(new LdapDomain(dn, attrs, this.prov.getConfig().getDomainDefaults(), this.prov));
/*  1986 */       } else if (objectclass.contains(AttributeClass.OC_zimbraCOS)) {
/*  1987 */         this.visitor.visit(new LdapCos(dn, attrs, this.prov));
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private List<NamedEntry> searchObjects(String[] bases, ZLdapFilter filter, String[] returnAttrs, SearchDirectoryOptions opts, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  2007 */     if (visitor != null) {
/*  2008 */       if (opts.getSortOpt() != SearchDirectoryOptions.SortOpt.NO_SORT) {
/*  2009 */         throw ServiceException.INVALID_REQUEST("Sorting is not supported with visitor interface", null);
/*       */       }
/*  2011 */       for (String base : bases) {
/*  2012 */         searchLdapObjects(base, filter, returnAttrs, opts, visitor);
/*       */       }
/*  2014 */       return null;
/*       */     }
/*  2016 */     final List<NamedEntry> result = new ArrayList();
/*       */     
/*  2018 */     NamedEntry.Visitor listBackedVisitor = new NamedEntry.Visitor()
/*       */     {
/*       */       public void visit(NamedEntry entry) {
/*  2021 */         result.add(entry);
/*       */       }
/*       */     };
/*       */     
/*  2025 */     for (String base : bases) {
/*  2026 */       searchLdapObjects(base, filter, returnAttrs, opts, listBackedVisitor);
/*       */     }
/*       */     
/*  2029 */     if (opts.getSortOpt() == SearchDirectoryOptions.SortOpt.NO_SORT) {
/*  2030 */       return result;
/*       */     }
/*  2032 */     NamedEntryComparator comparator = new NamedEntryComparator(this, opts.getSortAttr(), opts.getSortOpt() == SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*       */     
/*       */ 
/*  2035 */     Collections.sort(result, comparator);
/*  2036 */     return result;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   private void searchLdapObjects(String base, ZLdapFilter filter, String[] returnAttrs, SearchDirectoryOptions opts, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  2044 */     ZLdapContext zlc = null;
/*       */     try {
/*  2046 */       zlc = LdapClient.getContext(LdapServerType.get(opts.getOnMaster()), opts.getUseConnPool(), LdapUsage.SEARCH);
/*       */       
/*  2048 */       SearchObjectsVisitor searchObjectsVisitor = new SearchObjectsVisitor(this, zlc, visitor, opts.getMaxResults(), opts.getMakeObjectOpt(), returnAttrs, null);
/*       */       
/*       */ 
/*       */ 
/*  2052 */       SearchLdapOptions searchObjectsOptions = new SearchLdapOptions(base, filter, returnAttrs, opts.getMaxResults(), null, ZSearchScope.SEARCH_SCOPE_SUBTREE, searchObjectsVisitor);
/*       */       
/*       */ 
/*  2055 */       searchObjectsOptions.setUseControl(opts.isUseControl());
/*  2056 */       searchObjectsOptions.setManageDSAit(opts.isManageDSAit());
/*  2057 */       zlc.searchPaged(searchObjectsOptions);
/*       */     } catch (LdapException.LdapSizeLimitExceededException e) {
/*  2059 */       throw AccountServiceException.TOO_MANY_SEARCH_RESULTS("too many search results returned", e);
/*       */     } catch (ServiceException e) {
/*  2061 */       throw ServiceException.FAILURE("unable to list all objects", e);
/*       */     } finally {
/*  2063 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private String[] fixReturnAttrs(String[] returnAttrs, int flags)
/*       */   {
/*  2074 */     if ((returnAttrs == null) || (returnAttrs.length == 0)) {
/*  2075 */       return null;
/*       */     }
/*  2077 */     boolean needUID = true;
/*  2078 */     boolean needID = true;
/*  2079 */     boolean needCOSId = true;
/*  2080 */     boolean needObjectClass = true;
/*  2081 */     boolean needAliasTargetId = (flags & 0x2) != 0;
/*  2082 */     boolean needCalendarUserType = (flags & 0x8) != 0;
/*  2083 */     boolean needDomainName = true;
/*  2084 */     boolean needZimbraACE = true;
/*  2085 */     boolean needCn = ((flags & 0x20) != 0) || ((flags & 0x100) != 0);
/*  2086 */     boolean needIsExternalVirtualAccount = (flags & 0x1) != 0;
/*  2087 */     boolean needExternalUserMailAddress = (flags & 0x1) != 0;
/*       */     
/*  2089 */     for (int i = 0; i < returnAttrs.length; i++) {
/*  2090 */       if ("uid".equalsIgnoreCase(returnAttrs[i])) {
/*  2091 */         needUID = false;
/*  2092 */       } else if ("zimbraId".equalsIgnoreCase(returnAttrs[i])) {
/*  2093 */         needID = false;
/*  2094 */       } else if ("zimbraCOSId".equalsIgnoreCase(returnAttrs[i])) {
/*  2095 */         needCOSId = false;
/*  2096 */       } else if ("zimbraAliasTargetId".equalsIgnoreCase(returnAttrs[i])) {
/*  2097 */         needAliasTargetId = false;
/*  2098 */       } else if ("objectClass".equalsIgnoreCase(returnAttrs[i])) {
/*  2099 */         needObjectClass = false;
/*  2100 */       } else if ("zimbraAccountCalendarUserType".equalsIgnoreCase(returnAttrs[i])) {
/*  2101 */         needCalendarUserType = false;
/*  2102 */       } else if ("zimbraDomainName".equalsIgnoreCase(returnAttrs[i])) {
/*  2103 */         needDomainName = false;
/*  2104 */       } else if ("zimbraACE".equalsIgnoreCase(returnAttrs[i])) {
/*  2105 */         needZimbraACE = false;
/*  2106 */       } else if ("cn".equalsIgnoreCase(returnAttrs[i])) {
/*  2107 */         needCn = false;
/*  2108 */       } else if ("zimbraIsExternalVirtualAccount".equalsIgnoreCase(returnAttrs[i])) {
/*  2109 */         needIsExternalVirtualAccount = false;
/*  2110 */       } else if ("zimbraExternalUserMailAddress".equalsIgnoreCase(returnAttrs[i])) {
/*  2111 */         needExternalUserMailAddress = false;
/*       */       }
/*       */     }
/*  2114 */     int num = (needUID ? 1 : 0) + (needID ? 1 : 0) + (needCOSId ? 1 : 0) + (needAliasTargetId ? 1 : 0) + (needObjectClass ? 1 : 0) + (needCalendarUserType ? 1 : 0) + (needDomainName ? 1 : 0) + (needZimbraACE ? 1 : 0) + (needCn ? 1 : 0) + (needIsExternalVirtualAccount ? 1 : 0) + (needExternalUserMailAddress ? 1 : 0);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  2126 */     if (num == 0) { return returnAttrs;
/*       */     }
/*  2128 */     String[] result = new String[returnAttrs.length + num];
/*  2129 */     int i = 0;
/*  2130 */     if (needUID) result[(i++)] = "uid";
/*  2131 */     if (needID) result[(i++)] = "zimbraId";
/*  2132 */     if (needCOSId) result[(i++)] = "zimbraCOSId";
/*  2133 */     if (needAliasTargetId) result[(i++)] = "zimbraAliasTargetId";
/*  2134 */     if (needObjectClass) result[(i++)] = "objectClass";
/*  2135 */     if (needCalendarUserType) result[(i++)] = "zimbraAccountCalendarUserType";
/*  2136 */     if (needDomainName) result[(i++)] = "zimbraDomainName";
/*  2137 */     if (needZimbraACE) result[(i++)] = "zimbraACE";
/*  2138 */     if (needCn) result[(i++)] = "cn";
/*  2139 */     if (needIsExternalVirtualAccount) result[(i++)] = "zimbraIsExternalVirtualAccount";
/*  2140 */     if (needExternalUserMailAddress) result[(i++)] = "zimbraExternalUserMailAddress";
/*  2141 */     System.arraycopy(returnAttrs, 0, result, i, returnAttrs.length);
/*  2142 */     return result;
/*       */   }
/*       */   
/*       */   public void setCOS(Account acct, Cos cos) throws ServiceException
/*       */   {
/*  2147 */     HashMap<String, String> attrs = new HashMap();
/*  2148 */     attrs.put("zimbraCOSId", cos.getId());
/*  2149 */     modifyAttrs(acct, attrs);
/*       */   }
/*       */   
/*       */   public void modifyAccountStatus(Account acct, String newStatus) throws ServiceException
/*       */   {
/*  2154 */     HashMap<String, String> attrs = new HashMap();
/*  2155 */     attrs.put("zimbraAccountStatus", newStatus);
/*  2156 */     modifyAttrs(acct, attrs);
/*       */   }
/*       */   
/*       */   static String[] addMultiValue(String[] values, String value)
/*       */   {
/*  2161 */     List<String> list = new ArrayList(Arrays.asList(values));
/*  2162 */     list.add(value);
/*  2163 */     return (String[])list.toArray(new String[list.size()]);
/*       */   }
/*       */   
/*       */   String[] addMultiValue(NamedEntry acct, String attr, String value) {
/*  2167 */     return addMultiValue(acct.getMultiAttr(attr), value);
/*       */   }
/*       */   
/*       */   public void addAlias(Account acct, String alias) throws ServiceException
/*       */   {
/*  2172 */     addAliasInternal(acct, alias);
/*       */   }
/*       */   
/*       */   public void removeAlias(Account acct, String alias) throws ServiceException
/*       */   {
/*  2177 */     this.accountCache.remove(acct);
/*  2178 */     removeAliasInternal(acct, alias);
/*       */   }
/*       */   
/*       */   public void addAlias(DistributionList dl, String alias) throws ServiceException
/*       */   {
/*  2183 */     addAliasInternal(dl, alias);
/*  2184 */     this.allDLs.addGroup(dl);
/*       */   }
/*       */   
/*       */   public void removeAlias(DistributionList dl, String alias) throws ServiceException
/*       */   {
/*  2189 */     this.groupCache.remove(dl);
/*  2190 */     removeAliasInternal(dl, alias);
/*  2191 */     this.allDLs.removeGroup(alias);
/*       */   }
/*       */   
/*       */   private boolean isEntryAlias(ZAttributes attrs) throws ServiceException
/*       */   {
/*  2196 */     Map<String, Object> entryAttrs = attrs.getAttrs();
/*  2197 */     Object ocs = entryAttrs.get("objectClass");
/*  2198 */     if ((ocs instanceof String))
/*  2199 */       return ((String)ocs).equalsIgnoreCase(AttributeClass.OC_zimbraAlias);
/*  2200 */     if ((ocs instanceof String[])) {
/*  2201 */       for (String oc : (String[])ocs) {
/*  2202 */         if (oc.equalsIgnoreCase(AttributeClass.OC_zimbraAlias))
/*  2203 */           return true;
/*       */       }
/*       */     }
/*  2206 */     return false;
/*       */   }
/*       */   
/*       */   private void addAliasInternal(NamedEntry entry, String alias) throws ServiceException
/*       */   {
/*  2211 */     LdapUsage ldapUsage = null;
/*       */     
/*  2213 */     String targetDomainName = null;
/*  2214 */     AliasedEntry aliasedEntry = null;
/*  2215 */     if ((entry instanceof Account)) {
/*  2216 */       aliasedEntry = (AliasedEntry)entry;
/*  2217 */       targetDomainName = ((Account)entry).getDomainName();
/*  2218 */       ldapUsage = LdapUsage.ADD_ALIAS_ACCOUNT;
/*  2219 */     } else if ((entry instanceof Group)) {
/*  2220 */       aliasedEntry = (AliasedEntry)entry;
/*  2221 */       ldapUsage = LdapUsage.ADD_ALIAS_DL;
/*  2222 */       targetDomainName = ((Group)entry).getDomainName();
/*       */     } else {
/*  2224 */       throw ServiceException.FAILURE("invalid entry type for alias", null);
/*       */     }
/*       */     
/*  2227 */     alias = alias.toLowerCase().trim();
/*  2228 */     alias = IDNUtil.toAsciiEmail(alias);
/*       */     
/*  2230 */     validEmailAddress(alias);
/*       */     
/*  2232 */     String[] parts = alias.split("@");
/*  2233 */     String aliasName = parts[0];
/*  2234 */     String aliasDomain = parts[1];
/*       */     
/*  2236 */     ZLdapContext zlc = null;
/*  2237 */     String aliasDn = null;
/*       */     try {
/*  2239 */       zlc = LdapClient.getContext(LdapServerType.MASTER, ldapUsage);
/*       */       
/*  2241 */       Domain domain = getDomainByAsciiName(aliasDomain, zlc);
/*  2242 */       if (domain == null) {
/*  2243 */         throw AccountServiceException.NO_SUCH_DOMAIN(aliasDomain);
/*       */       }
/*  2245 */       aliasDn = this.mDIT.aliasDN(((LdapEntry)entry).getDN(), targetDomainName, aliasName, aliasDomain);
/*       */       
/*       */ 
/*  2248 */       String aliasUuid = LdapUtil.generateUUID();
/*  2249 */       String targetEntryId = entry.getId();
/*       */       try {
/*  2251 */         zlc.createEntry(aliasDn, "zimbraAlias", new String[] { "uid", aliasName, "zimbraId", aliasUuid, "zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()), "zimbraAliasTargetId", targetEntryId });
/*       */ 
/*       */ 
/*       */ 
/*       */       }
/*       */       catch (LdapException.LdapEntryAlreadyExistException e)
/*       */       {
/*       */ 
/*       */ 
/*       */ 
/*  2261 */         ZAttributes attrs = this.helper.getAttributes(zlc, aliasDn);
/*       */         
/*       */ 
/*  2264 */         if (!isEntryAlias(attrs)) {
/*  2265 */           throw e;
/*       */         }
/*  2267 */         Alias aliasEntry = makeAlias(aliasDn, attrs);
/*  2268 */         NamedEntry targetEntry = searchAliasTarget(aliasEntry, false);
/*  2269 */         if (targetEntry == null)
/*       */         {
/*       */           try {
/*  2272 */             removeAliasInternal(null, alias);
/*       */           }
/*       */           catch (ServiceException se) {}
/*       */           
/*       */ 
/*       */ 
/*  2278 */           zlc.createEntry(aliasDn, "zimbraAlias", new String[] { "uid", aliasName, "zimbraId", aliasUuid, "zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()), "zimbraAliasTargetId", targetEntryId });
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */         }
/*  2284 */         else if (targetEntryId.equals(targetEntry.getId()))
/*       */         {
/*  2286 */           Set<String> mailAliases = entry.getMultiAttrSet("zimbraMailAlias");
/*  2287 */           Set<String> mails = entry.getMultiAttrSet("mail");
/*       */           
/*  2289 */           if ((mailAliases != null) && (mailAliases.contains(alias)) && (mails != null) && (mails.contains(alias)))
/*       */           {
/*  2291 */             throw e;
/*       */           }
/*  2293 */           ZimbraLog.account.warn("alias entry exists at " + aliasDn + ", but either mail or zimbraMailAlias of the target does not contain " + alias + ", adding " + alias + " to entry " + entry.getName());
/*       */ 
/*       */ 
/*       */         }
/*       */         else
/*       */         {
/*       */ 
/*  2300 */           throw e;
/*       */         }
/*       */       }
/*       */       
/*  2304 */       HashMap<String, String> attrs = new HashMap();
/*  2305 */       attrs.put("+zimbraMailAlias", alias);
/*  2306 */       attrs.put("+mail", alias);
/*       */       
/*       */ 
/*  2309 */       modifyAttrsInternal(entry, zlc, attrs);
/*  2310 */       removeExternalAddrsFromAllDynamicGroups(aliasedEntry.getAllAddrsSet(), zlc);
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  2312 */       throw AccountServiceException.ACCOUNT_EXISTS(alias, aliasDn, nabe);
/*       */     } catch (LdapException e) {
/*  2314 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  2316 */       throw e;
/*       */     } catch (ServiceException e) {
/*  2318 */       throw ServiceException.FAILURE("unable to create alias: " + e.getMessage(), e);
/*       */     } finally {
/*  2320 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void removeAliasInternal(NamedEntry entry, String alias)
/*       */     throws ServiceException
/*       */   {
/*  2347 */     LdapUsage ldapUsage = null;
/*  2348 */     if ((entry instanceof Account)) {
/*  2349 */       ldapUsage = LdapUsage.REMOVE_ALIAS_ACCOUNT;
/*  2350 */     } else if ((entry instanceof Group)) {
/*  2351 */       ldapUsage = LdapUsage.REMOVE_ALIAS_DL;
/*       */     } else {
/*  2353 */       ldapUsage = LdapUsage.REMOVE_ALIAS;
/*       */     }
/*       */     
/*  2356 */     ZLdapContext zlc = null;
/*       */     try {
/*  2358 */       zlc = LdapClient.getContext(LdapServerType.MASTER, ldapUsage);
/*       */       
/*  2360 */       alias = alias.toLowerCase();
/*  2361 */       alias = IDNUtil.toAsciiEmail(alias);
/*       */       
/*  2363 */       String[] parts = alias.split("@");
/*  2364 */       String aliasName = parts[0];
/*  2365 */       String aliasDomain = parts[1];
/*       */       
/*  2367 */       Domain domain = getDomainByAsciiName(aliasDomain, zlc);
/*  2368 */       if (domain == null) {
/*  2369 */         throw AccountServiceException.NO_SUCH_DOMAIN(aliasDomain);
/*       */       }
/*  2371 */       String targetDn = entry == null ? null : ((LdapEntry)entry).getDN();
/*  2372 */       String targetDomainName = null;
/*  2373 */       if (entry != null) {
/*  2374 */         if ((entry instanceof Account)) {
/*  2375 */           targetDomainName = ((Account)entry).getDomainName();
/*  2376 */         } else if ((entry instanceof Group)) {
/*  2377 */           targetDomainName = ((Group)entry).getDomainName();
/*       */         } else {
/*  2379 */           throw ServiceException.INVALID_REQUEST("invalid entry type for alias", null);
/*       */         }
/*       */       }
/*  2382 */       String aliasDn = this.mDIT.aliasDN(targetDn, targetDomainName, aliasName, aliasDomain);
/*       */       
/*  2384 */       ZAttributes aliasAttrs = null;
/*  2385 */       Alias aliasEntry = null;
/*       */       try {
/*  2387 */         aliasAttrs = this.helper.getAttributes(zlc, aliasDn);
/*       */         
/*       */ 
/*  2390 */         if (!isEntryAlias(aliasAttrs)) {
/*  2391 */           throw AccountServiceException.NO_SUCH_ALIAS(alias);
/*       */         }
/*  2393 */         aliasEntry = makeAlias(aliasDn, aliasAttrs);
/*       */       } catch (ServiceException e) {
/*  2395 */         ZimbraLog.account.warn("alias " + alias + " does not exist");
/*       */       }
/*       */       
/*  2398 */       NamedEntry targetEntry = null;
/*  2399 */       if (aliasEntry != null) {
/*  2400 */         targetEntry = searchAliasTarget(aliasEntry, false);
/*       */       }
/*  2402 */       boolean aliasPointsToEntry = (entry != null) && (aliasEntry != null) && (entry.getId().equals(aliasEntry.getAttr("zimbraAliasTargetId")));
/*       */       
/*       */ 
/*  2405 */       boolean aliasPointsToOtherExistingEntry = (aliasEntry != null) && (targetEntry != null) && ((entry == null) || (!entry.getId().equals(targetEntry.getId())));
/*       */       
/*       */ 
/*  2408 */       boolean aliasPointsToNonExistingEntry = (aliasEntry != null) && (targetEntry == null);
/*       */       
/*       */ 
/*  2411 */       if (entry != null) {
/*       */         try {
/*  2413 */           HashMap<String, String> attrs = new HashMap();
/*  2414 */           attrs.put("-mail", alias);
/*  2415 */           attrs.put("-zimbraMailAlias", alias);
/*  2416 */           modifyAttrsInternal(entry, zlc, attrs);
/*       */         } catch (ServiceException e) {
/*  2418 */           ZimbraLog.account.warn("unable to remove zimbraMailAlias/mail attrs: " + alias);
/*       */         }
/*       */       }
/*       */       
/*       */ 
/*  2423 */       if (!aliasPointsToOtherExistingEntry) {
/*  2424 */         removeAddressFromAllDistributionLists(alias);
/*       */       }
/*       */       
/*       */ 
/*  2428 */       if ((aliasPointsToEntry) || (aliasPointsToNonExistingEntry)) {
/*       */         try {
/*  2430 */           zlc.deleteEntry(aliasDn);
/*       */         }
/*       */         catch (ServiceException e) {
/*  2433 */           ZimbraLog.account.warn("unable to remove alias entry at : " + aliasDn);
/*       */         }
/*       */       }
/*       */       
/*       */ 
/*  2438 */       if (((entry != null) && (aliasEntry == null)) || ((entry != null) && (aliasEntry != null) && (!aliasPointsToEntry)))
/*       */       {
/*  2440 */         throw AccountServiceException.NO_SUCH_ALIAS(alias);
/*       */       }
/*       */     } finally {
/*  2443 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public NamedEntry getAliasTarget(Alias alias, boolean mustFind)
/*       */     throws ServiceException
/*       */   {
/*  2458 */     String targetId = alias.getAttr("zimbraAliasTargetId");
/*       */     
/*       */ 
/*       */ 
/*  2462 */     NamedEntry target = get(Key.AccountBy.id, targetId);
/*  2463 */     if (target != null) {
/*  2464 */       return target;
/*       */     }
/*       */     
/*       */ 
/*  2468 */     target = getGroupBasic(Key.DistributionListBy.id, targetId);
/*       */     
/*  2470 */     return target;
/*       */   }
/*       */   
/*       */   public Domain createDomain(String name, Map<String, Object> domainAttrs)
/*       */     throws ServiceException
/*       */   {
/*  2476 */     name = name.toLowerCase().trim();
/*  2477 */     name = IDNUtil.toAsciiDomainName(name);
/*       */     
/*  2479 */     NameUtil.validNewDomainName(name);
/*       */     
/*  2481 */     ZLdapContext zlc = null;
/*       */     try {
/*  2483 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_DOMAIN);
/*       */       
/*  2485 */       LdapDomain d = (LdapDomain)getDomainByAsciiName(name, zlc);
/*  2486 */       if (d != null) {
/*  2487 */         throw AccountServiceException.DOMAIN_EXISTS(name);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  2492 */       String domainType = (String)domainAttrs.get("zimbraDomainType");
/*  2493 */       if (domainType == null) {
/*  2494 */         domainType = ZAttrProvisioning.DomainType.local.name();
/*       */       } else {
/*  2496 */         domainAttrs.remove("zimbraDomainType");
/*       */       }
/*       */       
/*  2499 */       String domainStatus = (String)domainAttrs.get("zimbraDomainStatus");
/*  2500 */       if (domainStatus == null) {
/*  2501 */         domainStatus = "active";
/*       */       } else {
/*  2503 */         domainAttrs.remove("zimbraDomainStatus");
/*       */       }
/*       */       
/*  2506 */       String smimeLdapURL = (String)domainAttrs.get("zimbraSMIMELdapURL");
/*  2507 */       if (!StringUtil.isNullOrEmpty(smimeLdapURL)) {
/*  2508 */         domainAttrs.remove("zimbraSMIMELdapURL");
/*       */       }
/*  2510 */       String smimeLdapStartTlsEnabled = (String)domainAttrs.get("zimbraSMIMELdapStartTlsEnabled");
/*  2511 */       if (!StringUtil.isNullOrEmpty(smimeLdapStartTlsEnabled)) {
/*  2512 */         domainAttrs.remove("zimbraSMIMELdapStartTlsEnabled");
/*       */       }
/*  2514 */       String smimeLdapBindDn = (String)domainAttrs.get("zimbraSMIMELdapBindDn");
/*  2515 */       if (!StringUtil.isNullOrEmpty(smimeLdapBindDn)) {
/*  2516 */         domainAttrs.remove("zimbraSMIMELdapBindDn");
/*       */       }
/*  2518 */       String smimeLdapBindPassword = (String)domainAttrs.get("zimbraSMIMELdapBindPassword");
/*  2519 */       if (!StringUtil.isNullOrEmpty(smimeLdapBindPassword)) {
/*  2520 */         domainAttrs.remove("zimbraSMIMELdapBindPassword");
/*       */       }
/*  2522 */       String smimeLdapSearchBase = (String)domainAttrs.get("zimbraSMIMELdapSearchBase");
/*  2523 */       if (!StringUtil.isNullOrEmpty(smimeLdapSearchBase)) {
/*  2524 */         domainAttrs.remove("zimbraSMIMELdapSearchBase");
/*       */       }
/*  2526 */       String smimeLdapFilter = (String)domainAttrs.get("zimbraSMIMELdapFilter");
/*  2527 */       if (!StringUtil.isNullOrEmpty(smimeLdapFilter)) {
/*  2528 */         domainAttrs.remove("zimbraSMIMELdapFilter");
/*       */       }
/*  2530 */       String smimeLdapAttribute = (String)domainAttrs.get("zimbraSMIMELdapAttribute");
/*  2531 */       if (!StringUtil.isNullOrEmpty(smimeLdapAttribute)) {
/*  2532 */         domainAttrs.remove("zimbraSMIMELdapAttribute");
/*       */       }
/*       */       
/*  2535 */       CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  2536 */       AttributeManager.getInstance().preModify(domainAttrs, null, callbackContext, true);
/*       */       
/*       */ 
/*  2539 */       domainAttrs.put("zimbraDomainType", domainType);
/*  2540 */       domainAttrs.put("zimbraDomainStatus", domainStatus);
/*  2541 */       domainAttrs.put("zimbraSMIMELdapURL", smimeLdapURL);
/*  2542 */       domainAttrs.put("zimbraSMIMELdapStartTlsEnabled", smimeLdapStartTlsEnabled);
/*  2543 */       domainAttrs.put("zimbraSMIMELdapBindDn", smimeLdapBindDn);
/*  2544 */       domainAttrs.put("zimbraSMIMELdapBindPassword", smimeLdapBindPassword);
/*  2545 */       domainAttrs.put("zimbraSMIMELdapSearchBase", smimeLdapSearchBase);
/*  2546 */       domainAttrs.put("zimbraSMIMELdapFilter", smimeLdapFilter);
/*  2547 */       domainAttrs.put("zimbraSMIMELdapAttribute", smimeLdapAttribute);
/*       */       
/*  2549 */       String[] parts = name.split("\\.");
/*  2550 */       String[] dns = this.mDIT.domainToDNs(parts);
/*  2551 */       createParentDomains(zlc, parts, dns);
/*       */       
/*  2553 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  2554 */       entry.mapToAttrs(domainAttrs);
/*       */       
/*  2556 */       Set<String> ocs = LdapObjectClass.getDomainObjectClasses(this);
/*  2557 */       entry.addAttr("objectClass", ocs);
/*       */       
/*  2559 */       String zimbraIdStr = LdapUtil.generateUUID();
/*  2560 */       entry.setAttr("zimbraId", zimbraIdStr);
/*  2561 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*  2562 */       entry.setAttr("zimbraDomainName", name);
/*       */       
/*  2564 */       String mailStatus = (String)domainAttrs.get("zimbraMailStatus");
/*  2565 */       if (mailStatus == null) {
/*  2566 */         entry.setAttr("zimbraMailStatus", "enabled");
/*       */       }
/*  2568 */       if (domainType.equalsIgnoreCase(ZAttrProvisioning.DomainType.alias.name())) {
/*  2569 */         entry.setAttr("zimbraMailCatchAllAddress", "@" + name);
/*       */       }
/*       */       
/*  2572 */       entry.setAttr("o", name + " domain");
/*  2573 */       entry.setAttr("dc", parts[0]);
/*       */       
/*  2575 */       String dn = dns[0];
/*  2576 */       entry.setDN(dn);
/*       */       try
/*       */       {
/*  2579 */         zlc.createEntry(entry);
/*       */       } catch (LdapException.LdapEntryAlreadyExistException e) {
/*  2581 */         zlc.replaceAttributes(dn, entry.getAttributes());
/*       */       }
/*       */       
/*  2584 */       String acctBaseDn = this.mDIT.domainDNToAccountBaseDN(dn);
/*  2585 */       if (!acctBaseDn.equals(dn))
/*       */       {
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  2594 */         zlc.createEntry(this.mDIT.domainDNToAccountBaseDN(dn), "organizationalRole", new String[] { "ou", "people", "cn", "people" });
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*  2599 */         zlc.createEntry(this.mDIT.domainDNToDynamicGroupsBaseDN(dn), "organizationalRole", new String[] { "cn", "groups", "description", "dynamic groups base" });
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  2604 */       Domain domain = getDomainById(zimbraIdStr, zlc);
/*       */       
/*  2606 */       AttributeManager.getInstance().postModify(domainAttrs, domain, callbackContext);
/*  2607 */       return domain;
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  2610 */       throw AccountServiceException.DOMAIN_EXISTS(name);
/*       */     } catch (LdapException e) {
/*  2612 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  2614 */       throw e;
/*       */     } catch (ServiceException e) {
/*  2616 */       throw ServiceException.FAILURE("unable to create domain: " + name, e);
/*       */     } finally {
/*  2618 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   private LdapDomain getDomainByQuery(ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*       */     try {
/*  2625 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.domainBaseDN(), filter, initZlc, false);
/*  2626 */       if (sr != null) {
/*  2627 */         return new LdapDomain(sr.getDN(), sr.getAttributes(), getConfig().getDomainDefaults(), this);
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  2630 */       throw AccountServiceException.MULTIPLE_DOMAINS_MATCHED("getDomainByQuery: " + e.getMessage());
/*       */     } catch (ServiceException e) {
/*  2632 */       throw ServiceException.FAILURE("unable to lookup domain via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  2635 */     return null;
/*       */   }
/*       */   
/*       */   public Domain get(Key.DomainBy keyType, String key) throws ServiceException
/*       */   {
/*  2640 */     return getDomain(keyType, key, false);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public Domain getDomain(Key.DomainBy keyType, String key, boolean checkNegativeCache)
/*       */     throws ServiceException
/*       */   {
/*  2650 */     DomainCache.GetFromDomainCacheOption option = checkNegativeCache ? DomainCache.GetFromDomainCacheOption.BOTH : DomainCache.GetFromDomainCacheOption.POSITIVE;
/*       */     
/*       */ 
/*  2653 */     switch (keyType) {
/*       */     case name: 
/*  2655 */       return getDomainByNameInternal(key, option);
/*       */     case id: 
/*  2657 */       return getDomainByIdInternal(key, null, option);
/*       */     case virtualHostname: 
/*  2659 */       return getDomainByVirtualHostnameInternal(key, DomainCache.GetFromDomainCacheOption.BOTH);
/*       */     case foreignName: 
/*  2661 */       return getDomainByForeignNameInternal(key, DomainCache.GetFromDomainCacheOption.BOTH);
/*       */     case krb5Realm: 
/*  2663 */       return getDomainByKrb5RealmInternal(key, DomainCache.GetFromDomainCacheOption.BOTH);
/*       */     }
/*  2665 */     return null;
/*       */   }
/*       */   
/*       */   private Domain getFromCache(Key.DomainBy keyType, String key, DomainCache.GetFromDomainCacheOption option)
/*       */   {
/*  2670 */     switch (keyType) {
/*       */     case name: 
/*  2672 */       String asciiName = IDNUtil.toAsciiDomainName(key);
/*  2673 */       return this.domainCache.getByName(asciiName, option);
/*       */     case id: 
/*  2675 */       return this.domainCache.getById(key, option);
/*       */     case virtualHostname: 
/*  2677 */       return this.domainCache.getByVirtualHostname(key, option);
/*       */     case krb5Realm: 
/*  2679 */       return this.domainCache.getByKrb5Realm(key, option);
/*       */     }
/*  2681 */     return null;
/*       */   }
/*       */   
/*       */   private Domain getDomainById(String zimbraId, ZLdapContext zlc) throws ServiceException
/*       */   {
/*  2686 */     return getDomainByIdInternal(zimbraId, zlc, DomainCache.GetFromDomainCacheOption.POSITIVE);
/*       */   }
/*       */   
/*       */   private Domain getDomainByIdInternal(String zimbraId, ZLdapContext zlc, DomainCache.GetFromDomainCacheOption option) throws ServiceException
/*       */   {
/*  2691 */     if (zimbraId == null) {
/*  2692 */       return null;
/*       */     }
/*       */     
/*  2695 */     Domain d = this.domainCache.getById(zimbraId, option);
/*  2696 */     if ((d instanceof DomainCache.NonExistingDomain)) {
/*  2697 */       return null;
/*       */     }
/*       */     
/*  2700 */     LdapDomain domain = (LdapDomain)d;
/*  2701 */     if (domain == null) {
/*  2702 */       domain = getDomainByQuery(this.filterFactory.domainById(zimbraId), zlc);
/*  2703 */       this.domainCache.put(Key.DomainBy.id, zimbraId, domain);
/*       */     }
/*  2705 */     return domain;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   private Domain getDomainByIdFromCache(String zimbraId, ZLdapContext zlc, DomainCache.GetFromDomainCacheOption option)
/*       */   {
/*  2713 */     if (zimbraId == null) {
/*  2714 */       return null;
/*       */     }
/*  2716 */     Domain d = this.domainCache.getById(zimbraId, option);
/*  2717 */     if ((d instanceof DomainCache.NonExistingDomain)) {
/*  2718 */       return null;
/*       */     }
/*  2720 */     LdapDomain domain = (LdapDomain)d;
/*  2721 */     return domain;
/*       */   }
/*       */   
/*       */   private Domain getDomainByNameInternal(String name, DomainCache.GetFromDomainCacheOption option) throws ServiceException
/*       */   {
/*  2726 */     String asciiName = IDNUtil.toAsciiDomainName(name);
/*  2727 */     return getDomainByAsciiNameInternal(asciiName, null, option);
/*       */   }
/*       */   
/*       */   private Domain getDomainByAsciiName(String name, ZLdapContext zlc) throws ServiceException
/*       */   {
/*  2732 */     return getDomainByAsciiNameInternal(name, zlc, DomainCache.GetFromDomainCacheOption.POSITIVE);
/*       */   }
/*       */   
/*       */   private Domain getDomainByAsciiNameInternal(String name, ZLdapContext zlc, DomainCache.GetFromDomainCacheOption option)
/*       */     throws ServiceException
/*       */   {
/*  2738 */     Domain d = this.domainCache.getByName(name, option);
/*  2739 */     if ((d instanceof DomainCache.NonExistingDomain)) {
/*  2740 */       return null;
/*       */     }
/*  2742 */     LdapDomain domain = (LdapDomain)d;
/*  2743 */     if (domain == null) {
/*  2744 */       domain = getDomainByQuery(this.filterFactory.domainByName(name), zlc);
/*  2745 */       this.domainCache.put(Key.DomainBy.name, name, domain);
/*       */     }
/*  2747 */     return domain;
/*       */   }
/*       */   
/*       */   private Domain getDomainByVirtualHostnameInternal(String virtualHostname, DomainCache.GetFromDomainCacheOption option)
/*       */     throws ServiceException
/*       */   {
/*  2753 */     Domain d = this.domainCache.getByVirtualHostname(virtualHostname, option);
/*  2754 */     if ((d instanceof DomainCache.NonExistingDomain)) {
/*  2755 */       return null;
/*       */     }
/*  2757 */     LdapDomain domain = (LdapDomain)d;
/*  2758 */     if (domain == null) {
/*  2759 */       domain = getDomainByQuery(this.filterFactory.domainByVirtualHostame(virtualHostname), null);
/*  2760 */       this.domainCache.put(Key.DomainBy.virtualHostname, virtualHostname, domain);
/*       */     }
/*  2762 */     return domain;
/*       */   }
/*       */   
/*       */   private Domain getDomainByForeignNameInternal(String foreignName, DomainCache.GetFromDomainCacheOption option)
/*       */     throws ServiceException
/*       */   {
/*  2768 */     Domain d = this.domainCache.getByForeignName(foreignName, option);
/*  2769 */     if ((d instanceof DomainCache.NonExistingDomain)) {
/*  2770 */       return null;
/*       */     }
/*  2772 */     LdapDomain domain = (LdapDomain)d;
/*  2773 */     if (domain == null) {
/*  2774 */       domain = getDomainByQuery(this.filterFactory.domainByForeignName(foreignName), null);
/*  2775 */       this.domainCache.put(Key.DomainBy.foreignName, foreignName, domain);
/*       */     }
/*  2777 */     return domain;
/*       */   }
/*       */   
/*       */   private Domain getDomainByKrb5RealmInternal(String krb5Realm, DomainCache.GetFromDomainCacheOption option)
/*       */     throws ServiceException
/*       */   {
/*  2783 */     Domain d = this.domainCache.getByKrb5Realm(krb5Realm, option);
/*  2784 */     if ((d instanceof DomainCache.NonExistingDomain)) {
/*  2785 */       return null;
/*       */     }
/*  2787 */     LdapDomain domain = (LdapDomain)d;
/*  2788 */     if (domain == null) {
/*  2789 */       domain = getDomainByQuery(this.filterFactory.domainByKrb5Realm(krb5Realm), null);
/*  2790 */       this.domainCache.put(Key.DomainBy.krb5Realm, krb5Realm, domain);
/*       */     }
/*  2792 */     return domain;
/*       */   }
/*       */   
/*  2795 */   private static final String[] ZIMBRA_ID_ATTR = { "zimbraId" };
/*  2796 */   private static final Set<SearchDirectoryOptions.ObjectType> DOMAINS_OBJECT_TYPE = Sets.newHashSet(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.domains });
/*       */   public static final long TIMESTAMP_WINDOW = 300000L;
/*       */   private static final int DEFAULT_GAL_MAX_RESULTS = 100;
/*       */   
/*  2800 */   public List<Domain> getAllDomains() throws ServiceException { List<Domain> result = new ArrayList();
/*  2801 */     AllDomainIdsCollector collector = new AllDomainIdsCollector(null);
/*  2802 */     BySearchResultEntrySearcher searcher = new BySearchResultEntrySearcher(this, null, (Domain)null, ZIMBRA_ID_ATTR, collector);
/*       */     
/*  2804 */     searcher.doSearch(this.filterFactory.allDomains(), DOMAINS_OBJECT_TYPE);
/*  2805 */     List<String> cacheMisses = Lists.newArrayList();
/*  2806 */     for (String zimbraId : collector.domains) {
/*  2807 */       Domain cachedDom = getDomainByIdFromCache(zimbraId, null, DomainCache.GetFromDomainCacheOption.POSITIVE);
/*  2808 */       if (cachedDom == null) {
/*  2809 */         cacheMisses.add(zimbraId);
/*       */       } else {
/*  2811 */         result.add(cachedDom);
/*       */       }
/*       */     }
/*  2814 */     if (!cacheMisses.isEmpty()) {
/*  2815 */       boolean cacheDomains = LC.ldap_cache_domain_maxsize.intValue() >= collector.domains.size();
/*  2816 */       if (!cacheDomains) {
/*  2817 */         ZimbraLog.search.info("localconfig ldap_cache_domain_maxsize=%d < number of domains=%d.  Consider increasing it.", new Object[] { Integer.valueOf(LC.ldap_cache_domain_maxsize.intValue()), Integer.valueOf(collector.domains.size()) });
/*       */       }
/*       */       
/*       */ 
/*  2821 */       getDomainsByIds(new DomainsByIdsVisitor(result, cacheDomains, null), cacheMisses, null);
/*       */     }
/*  2823 */     return result;
/*       */   }
/*       */   
/*       */   private static class AllDomainIdsCollector implements BySearchResultEntrySearcher.SearchEntryProcessor {
/*  2827 */     public final List<String> domains = Lists.newArrayList();
/*       */     
/*       */     public void processSearchEntry(ZSearchResultEntry sr)
/*       */     {
/*  2831 */       ZAttributes attrs = sr.getAttributes();
/*       */       try {
/*  2833 */         this.domains.add(attrs.getAttrString("zimbraId"));
/*       */       } catch (ServiceException e) {
/*  2835 */         ZimbraLog.search.debug("Problem processing search result entry - ignoring", e);
/*  2836 */         return;
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   private class DomainsByIdsVisitor implements NamedEntry.Visitor {
/*       */     private final List<Domain> result;
/*       */     private final boolean cacheResults;
/*       */     
/*  2845 */     private DomainsByIdsVisitor(boolean result) { this.result = result;
/*  2846 */       this.cacheResults = cacheResults;
/*       */     }
/*       */     
/*       */     public void visit(NamedEntry entry) {
/*  2850 */       this.result.add((LdapDomain)entry);
/*  2851 */       if (this.cacheResults) {
/*  2852 */         LdapProvisioning.this.domainCache.put(Key.DomainBy.id, entry.getId(), (Domain)entry);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   public void getDomainsByIds(NamedEntry.Visitor visitor, Collection<String> domains, String[] retAttrs) throws ServiceException
/*       */   {
/*  2859 */     SearchDirectoryOptions opts = new SearchDirectoryOptions(retAttrs);
/*  2860 */     opts.setFilter(this.filterFactory.domainsByIds(domains));
/*  2861 */     opts.setTypes(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.domains });
/*  2862 */     searchDirectoryInternal(opts, visitor);
/*       */   }
/*       */   
/*       */   public void getAllDomains(NamedEntry.Visitor visitor, String[] retAttrs)
/*       */     throws ServiceException
/*       */   {
/*  2868 */     SearchDirectoryOptions opts = new SearchDirectoryOptions(retAttrs);
/*  2869 */     opts.setFilter(this.filterFactory.allDomains());
/*  2870 */     opts.setTypes(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.domains });
/*  2871 */     searchDirectoryInternal(opts, visitor);
/*       */   }
/*       */   
/*       */   private boolean domainDnExists(ZLdapContext zlc, String dn) throws ServiceException {
/*       */     try {
/*  2876 */       ZSearchResultEnumeration ne = this.helper.searchDir(dn, this.filterFactory.domainLabel(), ZSearchControls.SEARCH_CTLS_SUBTREE(), zlc, LdapServerType.MASTER);
/*       */       
/*  2878 */       boolean result = ne.hasMore();
/*  2879 */       ne.close();
/*  2880 */       return result;
/*       */     } catch (ServiceException e) {}
/*  2882 */     return false;
/*       */   }
/*       */   
/*       */   private void createParentDomains(ZLdapContext zlc, String[] parts, String[] dns)
/*       */     throws ServiceException
/*       */   {
/*  2888 */     for (int i = dns.length - 1; i > 0; i--) {
/*  2889 */       if (!domainDnExists(zlc, dns[i])) {
/*  2890 */         String dn = dns[i];
/*  2891 */         String domain = parts[i];
/*       */         
/*  2893 */         zlc.createEntry(dn, new String[] { "dcObject", "organization" }, new String[] { "o", domain + " domain", "dc", domain });
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   public Cos createCos(String name, Map<String, Object> cosAttrs)
/*       */     throws ServiceException
/*       */   {
/*  2901 */     String defaultCosId = getCosByName("default", null).getId();
/*  2902 */     return copyCos(defaultCosId, name, cosAttrs);
/*       */   }
/*       */   
/*       */   public Cos copyCos(String srcCosId, String destCosName) throws ServiceException
/*       */   {
/*  2907 */     return copyCos(srcCosId, destCosName, null);
/*       */   }
/*       */   
/*       */   private Cos copyCos(String srcCosId, String destCosName, Map<String, Object> cosAttrs) throws ServiceException
/*       */   {
/*  2912 */     destCosName = destCosName.toLowerCase().trim();
/*       */     
/*  2914 */     Cos srcCos = getCosById(srcCosId, null);
/*  2915 */     if (srcCos == null) {
/*  2916 */       throw AccountServiceException.NO_SUCH_COS(srcCosId);
/*       */     }
/*       */     
/*       */ 
/*  2920 */     Map<String, Object> allAttrs = new java.util.TreeMap(String.CASE_INSENSITIVE_ORDER);
/*       */     
/*  2922 */     allAttrs.putAll(srcCos.getAttrs());
/*       */     
/*  2924 */     allAttrs.remove("objectClass");
/*  2925 */     allAttrs.remove("zimbraId");
/*  2926 */     allAttrs.remove("zimbraCreateTimestamp");
/*  2927 */     allAttrs.remove("zimbraACE");
/*  2928 */     allAttrs.remove("cn");
/*  2929 */     allAttrs.remove("description");
/*  2930 */     if (cosAttrs != null) {
/*  2931 */       for (Map.Entry<String, Object> e : cosAttrs.entrySet()) {
/*  2932 */         String attr = (String)e.getKey();
/*  2933 */         Object value = e.getValue();
/*  2934 */         if (((value instanceof String)) && (Strings.isNullOrEmpty((String)value))) {
/*  2935 */           allAttrs.remove(attr);
/*       */         } else {
/*  2937 */           allAttrs.put(attr, value);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*  2942 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*       */     
/*       */ 
/*  2945 */     Map<String, Object> allNewAttrs = new HashMap(allAttrs);
/*  2946 */     for (String attr : allAttrs.keySet()) {
/*  2947 */       AttributeInfo info = AttributeManager.getInstance().getAttributeInfo(attr);
/*  2948 */       if ((info != null) && (info.isDeprecated())) {
/*  2949 */         allNewAttrs.remove(attr);
/*       */       }
/*       */     }
/*  2952 */     allAttrs = allNewAttrs;
/*  2953 */     AttributeManager.getInstance().preModify(allAttrs, null, callbackContext, true);
/*       */     
/*  2955 */     ZLdapContext zlc = null;
/*       */     try {
/*  2957 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_COS);
/*       */       
/*  2959 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  2960 */       entry.mapToAttrs(allAttrs);
/*       */       
/*  2962 */       Set<String> ocs = LdapObjectClass.getCosObjectClasses(this);
/*  2963 */       entry.addAttr("objectClass", ocs);
/*       */       
/*  2965 */       String zimbraIdStr = LdapUtil.generateUUID();
/*  2966 */       entry.setAttr("zimbraId", zimbraIdStr);
/*  2967 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*  2968 */       entry.setAttr("cn", destCosName);
/*  2969 */       String dn = this.mDIT.cosNametoDN(destCosName);
/*  2970 */       entry.setDN(dn);
/*  2971 */       zlc.createEntry(entry);
/*       */       
/*  2973 */       Cos cos = getCosById(zimbraIdStr, zlc);
/*  2974 */       AttributeManager.getInstance().postModify(allAttrs, cos, callbackContext);
/*  2975 */       return cos;
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  2977 */       throw AccountServiceException.COS_EXISTS(destCosName);
/*       */     } catch (LdapException e) {
/*  2979 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  2981 */       throw e;
/*       */     } catch (ServiceException e) {
/*  2983 */       throw ServiceException.FAILURE("unable to create cos: " + destCosName, e);
/*       */     } finally {
/*  2985 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void renameCos(String zimbraId, String newName) throws ServiceException
/*       */   {
/*  2991 */     LdapCos cos = (LdapCos)get(Key.CosBy.id, zimbraId);
/*  2992 */     if (cos == null) {
/*  2993 */       throw AccountServiceException.NO_SUCH_COS(zimbraId);
/*       */     }
/*  2995 */     if (cos.isDefaultCos()) {
/*  2996 */       throw ServiceException.INVALID_REQUEST("unable to rename default cos", null);
/*       */     }
/*  2998 */     newName = newName.toLowerCase().trim();
/*  2999 */     ZLdapContext zlc = null;
/*       */     try {
/*  3001 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_COS);
/*  3002 */       String newDn = this.mDIT.cosNametoDN(newName);
/*  3003 */       zlc.renameEntry(cos.getDN(), newDn);
/*       */       
/*  3005 */       this.cosCache.remove(cos);
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  3007 */       throw AccountServiceException.COS_EXISTS(newName);
/*       */     } catch (LdapException e) {
/*  3009 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  3011 */       throw e;
/*       */     } catch (ServiceException e) {
/*  3013 */       throw ServiceException.FAILURE("unable to rename cos: " + zimbraId, e);
/*       */     } finally {
/*  3015 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   private LdapCos getCOSByQuery(ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*       */     try {
/*  3022 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.cosBaseDN(), filter, initZlc, false);
/*  3023 */       if (sr != null) {
/*  3024 */         return new LdapCos(sr.getDN(), sr.getAttributes(), this);
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  3027 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getCOSByQuery", e);
/*       */     } catch (ServiceException e) {
/*  3029 */       throw ServiceException.FAILURE("unable to lookup cos via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  3032 */     return null;
/*       */   }
/*       */   
/*       */   private Cos getCosById(String zimbraId, ZLdapContext zlc) throws ServiceException {
/*  3036 */     if (zimbraId == null) {
/*  3037 */       return null;
/*       */     }
/*  3039 */     LdapCos cos = (LdapCos)this.cosCache.getById(zimbraId);
/*  3040 */     if (cos == null) {
/*  3041 */       cos = getCOSByQuery(this.filterFactory.cosById(zimbraId), zlc);
/*  3042 */       this.cosCache.put(cos);
/*       */     }
/*  3044 */     return cos;
/*       */   }
/*       */   
/*       */   public Cos get(Key.CosBy keyType, String key) throws ServiceException
/*       */   {
/*  3049 */     switch (keyType) {
/*       */     case name: 
/*  3051 */       return getCosByName(key, null);
/*       */     case id: 
/*  3053 */       return getCosById(key, null);
/*       */     }
/*  3055 */     return null;
/*       */   }
/*       */   
/*       */   private Cos getFromCache(Key.CosBy keyType, String key)
/*       */   {
/*  3060 */     switch (keyType) {
/*       */     case name: 
/*  3062 */       return (Cos)this.cosCache.getByName(key);
/*       */     case id: 
/*  3064 */       return (Cos)this.cosCache.getById(key);
/*       */     }
/*  3066 */     return null;
/*       */   }
/*       */   
/*       */   private Cos getCosByName(String name, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*  3071 */     LdapCos cos = (LdapCos)this.cosCache.getByName(name);
/*  3072 */     if (cos != null) {
/*  3073 */       return cos;
/*       */     }
/*       */     try {
/*  3076 */       String dn = this.mDIT.cosNametoDN(name);
/*  3077 */       ZAttributes attrs = this.helper.getAttributes(initZlc, LdapServerType.REPLICA, LdapUsage.GET_COS, dn, null);
/*       */       
/*  3079 */       cos = new LdapCos(dn, attrs, this);
/*  3080 */       this.cosCache.put(cos);
/*  3081 */       return cos;
/*       */     } catch (LdapException.LdapEntryNotFoundException e) {
/*  3083 */       return null;
/*       */     } catch (ServiceException e) {
/*  3085 */       throw ServiceException.FAILURE("unable to lookup COS by name: " + name + " message: " + e.getMessage(), e);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<Cos> getAllCos()
/*       */     throws ServiceException
/*       */   {
/*  3092 */     List<Cos> result = new ArrayList();
/*       */     try
/*       */     {
/*  3095 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.cosBaseDN(), this.filterFactory.allCoses(), ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*  3097 */       while (ne.hasMore()) {
/*  3098 */         ZSearchResultEntry sr = ne.next();
/*  3099 */         result.add(new LdapCos(sr.getDN(), sr.getAttributes(), this));
/*       */       }
/*  3101 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  3103 */       throw ServiceException.FAILURE("unable to list all COS", e);
/*       */     }
/*       */     
/*  3106 */     Collections.sort(result);
/*  3107 */     return result;
/*       */   }
/*       */   
/*       */   public void deleteAccount(String zimbraId) throws ServiceException
/*       */   {
/*  3112 */     Account acc = getAccountById(zimbraId);
/*  3113 */     LdapEntry entry = (LdapEntry)getAccountById(zimbraId);
/*  3114 */     if (acc == null) {
/*  3115 */       throw AccountServiceException.NO_SUCH_ACCOUNT(zimbraId);
/*       */     }
/*       */     
/*  3118 */     removeAddressFromAllDistributionLists(acc.getName());
/*       */     
/*       */ 
/*  3121 */     String[] aliases = acc.getMailAlias();
/*  3122 */     if (aliases != null) {
/*  3123 */       for (int i = 0; i < aliases.length; i++) {
/*       */         try {
/*  3125 */           removeAlias(acc, aliases[i]);
/*       */         } catch (ServiceException se) {
/*  3127 */           if ("account.NO_SUCH_ALIAS".equals(se.getCode())) {
/*  3128 */             ZimbraLog.account.warn("got no such alias from removeAlias call when deleting account; likely alias was previously in a bad state");
/*       */           } else {
/*  3130 */             throw se;
/*       */           }
/*       */         }
/*       */       }
/*       */     }
/*       */     try
/*       */     {
/*  3137 */       RightCommand.revokeAllRights(this, GranteeType.GT_USER, zimbraId);
/*       */     }
/*       */     catch (ServiceException e) {
/*  3140 */       ZimbraLog.account.warn("cannot revoke grants", e);
/*       */     }
/*  3142 */     Map<String, Object> attrs = new HashMap(acc.getAttrs());
/*  3143 */     ZLdapContext zlc = null;
/*       */     try {
/*  3145 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_ACCOUNT);
/*       */       
/*  3147 */       zlc.deleteChildren(entry.getDN());
/*  3148 */       zlc.deleteEntry(entry.getDN());
/*  3149 */       validate("deleteAccountSucceeded", new Object[] { attrs });
/*  3150 */       this.accountCache.remove(acc);
/*       */     } catch (ServiceException e) {
/*  3152 */       throw ServiceException.FAILURE("unable to purge account: " + zimbraId, e);
/*       */     } finally {
/*  3154 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void renameAccount(String zimbraId, String newName)
/*       */     throws ServiceException
/*       */   {
/*  3161 */     newName = IDNUtil.toAsciiEmail(newName);
/*  3162 */     validEmailAddress(newName);
/*       */     
/*  3164 */     ZLdapContext zlc = null;
/*       */     
/*  3166 */     Account acct = getAccountById(zimbraId, zlc, true);
/*       */     
/*       */ 
/*  3169 */     this.accountCache.remove(acct);
/*       */     
/*  3171 */     LdapEntry entry = (LdapEntry)acct;
/*  3172 */     if (acct == null)
/*  3173 */       throw AccountServiceException.NO_SUCH_ACCOUNT(zimbraId);
/*  3174 */     String oldEmail = acct.getName();
/*       */     
/*  3176 */     boolean domainChanged = false;
/*  3177 */     Account oldAccount = acct;
/*       */     try {
/*  3179 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_ACCOUNT);
/*       */       
/*  3181 */       String oldDn = entry.getDN();
/*  3182 */       String[] parts = EmailUtil.getLocalPartAndDomain(oldEmail);
/*  3183 */       String oldLocal = parts[0];
/*  3184 */       String oldDomain = parts[1];
/*       */       
/*  3186 */       newName = newName.toLowerCase().trim();
/*  3187 */       parts = EmailUtil.getLocalPartAndDomain(newName);
/*  3188 */       if (parts == null) {
/*  3189 */         throw ServiceException.INVALID_REQUEST("bad value for newName", null);
/*       */       }
/*  3191 */       String newLocal = parts[0];
/*  3192 */       String newDomain = parts[1];
/*       */       
/*  3194 */       Domain domain = getDomainByAsciiName(newDomain, zlc);
/*  3195 */       if (domain == null) {
/*  3196 */         throw AccountServiceException.NO_SUCH_DOMAIN(newDomain);
/*       */       }
/*       */       
/*  3199 */       domainChanged = !newDomain.equals(oldDomain);
/*       */       
/*  3201 */       if (domainChanged) {
/*  3202 */         validate("renameAccount", new Object[] { newName, acct.getMultiAttr("objectClass", false), acct.getAttrs(false) });
/*  3203 */         validate("renameAccountCheckDomainCosAndFeature", new Object[] { newName, acct.getAttrs(false) });
/*       */         
/*       */ 
/*  3206 */         if (!domain.isLocal()) {
/*  3207 */           throw ServiceException.INVALID_REQUEST("domain type must be local", null);
/*       */         }
/*       */       }
/*       */       
/*  3211 */       String newDn = this.mDIT.accountDNRename(oldDn, newLocal, domain.getName());
/*  3212 */       boolean dnChanged = !newDn.equals(oldDn);
/*       */       
/*  3214 */       Map<String, Object> newAttrs = acct.getAttrs(false);
/*       */       
/*  3216 */       if (dnChanged)
/*       */       {
/*       */ 
/*       */ 
/*  3220 */         newAttrs.remove("uid");
/*       */       } else {
/*  3222 */         newAttrs.put("uid", newLocal);
/*       */       }
/*       */       
/*  3225 */       newAttrs.put("zimbraMailDeliveryAddress", newName);
/*  3226 */       if (oldEmail.equals(newAttrs.get("zimbraPrefFromAddress")))
/*       */       {
/*  3228 */         newAttrs.put("zimbraPrefFromAddress", newName);
/*       */       }
/*       */       
/*  3231 */       ReplaceAddressResult replacedMails = replaceMailAddresses(acct, "mail", oldEmail, newName);
/*       */       
/*  3233 */       if (replacedMails.newAddrs().length == 0)
/*       */       {
/*  3235 */         newAttrs.put("mail", newName);
/*       */       } else {
/*  3237 */         newAttrs.put("mail", replacedMails.newAddrs());
/*       */       }
/*       */       
/*  3240 */       ReplaceAddressResult replacedAliases = replaceMailAddresses(acct, "zimbraMailAlias", oldEmail, newName);
/*       */       
/*  3242 */       if (replacedAliases.newAddrs().length > 0) {
/*  3243 */         newAttrs.put("zimbraMailAlias", replacedAliases.newAddrs());
/*       */         
/*  3245 */         String newDomainDN = this.mDIT.domainToAccountSearchDN(newDomain);
/*       */         
/*  3247 */         String[] aliasNewAddrs = replacedAliases.newAddrs();
/*       */         
/*       */ 
/*  3250 */         if ((domainChanged) && (addressExistsUnderDN(zlc, newDomainDN, aliasNewAddrs))) {
/*  3251 */           throw AccountServiceException.ACCOUNT_EXISTS(newName);
/*       */         }
/*       */         
/*       */ 
/*       */ 
/*  3256 */         for (int i = 0; i < aliasNewAddrs.length; i++) {
/*  3257 */           if (newName.equalsIgnoreCase(aliasNewAddrs[i])) {
/*  3258 */             throw AccountServiceException.ACCOUNT_EXISTS(newName);
/*       */           }
/*       */         }
/*       */       }
/*       */       
/*  3263 */       ReplaceAddressResult replacedAllowAddrForDelegatedSender = replaceMailAddresses(acct, "zimbraPrefAllowAddressForDelegatedSender", oldEmail, newName);
/*       */       
/*       */ 
/*  3266 */       if (replacedAllowAddrForDelegatedSender.newAddrs().length > 0) {
/*  3267 */         newAttrs.put("zimbraPrefAllowAddressForDelegatedSender", replacedAllowAddrForDelegatedSender.newAddrs());
/*       */       }
/*       */       
/*       */ 
/*  3271 */       if ((newAttrs.get("displayName") == null) && (oldLocal.equals(newAttrs.get("cn")))) {
/*  3272 */         newAttrs.put("cn", newLocal);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  3280 */       if (dnChanged) {
/*  3281 */         zlc.renameEntry(oldDn, newDn);
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*  3286 */         acct = getAccountByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.accountById(zimbraId), zlc, true);
/*  3287 */         if (acct == null) {
/*  3288 */           throw ServiceException.FAILURE("cannot find account by id after modrdn", null);
/*       */         }
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  3294 */       renameAddressesInAllDistributionLists(oldEmail, newName, replacedAliases);
/*       */       
/*       */ 
/*       */ 
/*  3298 */       if (domainChanged) {
/*  3299 */         moveAliases(zlc, replacedAliases, newDomain, null, oldDn, newDn, oldDomain, newDomain);
/*       */       }
/*       */       
/*  3302 */       modifyLdapAttrs(acct, zlc, newAttrs);
/*       */       
/*       */ 
/*  3305 */       acct = getAccountByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.accountById(zimbraId), zlc, true);
/*  3306 */       if (acct == null) {
/*  3307 */         throw ServiceException.FAILURE("cannot find account by id after modrdn", null);
/*       */       }
/*  3309 */       removeExternalAddrsFromAllDynamicGroups(acct.getAllAddrsSet(), zlc);
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  3311 */       throw AccountServiceException.ACCOUNT_EXISTS(newName);
/*       */     } catch (LdapException e) {
/*  3313 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  3315 */       throw e;
/*       */     } catch (ServiceException e) {
/*  3317 */       throw ServiceException.FAILURE("unable to rename account: " + newName, e);
/*       */     } finally {
/*  3319 */       LdapClient.closeContext(zlc);
/*       */       
/*  3321 */       this.accountCache.remove(oldAccount);
/*       */     }
/*       */     
/*       */ 
/*  3325 */     Account renamedAcct = getAccountById(zimbraId, null, true);
/*       */     
/*  3327 */     if (domainChanged) {
/*  3328 */       PermissionCache.invalidateCache(renamedAcct);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteDomain(String zimbraId) throws ServiceException
/*       */   {
/*  3334 */     ZLdapContext zlc = null;
/*       */     try {
/*  3336 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_DOMAIN);
/*       */       
/*  3338 */       Domain domain = getDomainById(zimbraId, zlc);
/*  3339 */       if (domain == null) {
/*  3340 */         throw AccountServiceException.NO_SUCH_DOMAIN(zimbraId);
/*       */       }
/*       */       
/*  3343 */       List<String> aliasDomainIds = null;
/*  3344 */       if (domain.isLocal()) {
/*  3345 */         aliasDomainIds = getEmptyAliasDomainIds(zlc, domain, true);
/*       */       }
/*       */       
/*       */ 
/*  3349 */       deleteDomainInternal(zlc, zimbraId);
/*       */       
/*       */ 
/*  3352 */       if (aliasDomainIds != null) {
/*  3353 */         for (String aliasDomainId : aliasDomainIds) {
/*  3354 */           deleteDomainInternal(zlc, aliasDomainId);
/*       */         }
/*       */       }
/*       */     }
/*       */     catch (ServiceException e) {
/*  3359 */       throw e;
/*       */     } finally {
/*  3361 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<String> getEmptyAliasDomainIds(ZLdapContext zlc, Domain targetDomain, boolean suboridinateCheck)
/*       */     throws ServiceException
/*       */   {
/*  3368 */     List<String> aliasDomainIds = new ArrayList();
/*       */     
/*  3370 */     ZSearchResultEnumeration ne = null;
/*       */     try {
/*  3372 */       ZSearchControls searchControls = ZSearchControls.createSearchControls(ZSearchScope.SEARCH_SCOPE_SUBTREE, 0, new String[] { "zimbraId", "zimbraDomainName" });
/*       */       
/*       */ 
/*       */ 
/*  3376 */       ne = this.helper.searchDir(this.mDIT.domainBaseDN(), this.filterFactory.domainAliases(targetDomain.getId()), searchControls, zlc, LdapServerType.MASTER);
/*       */       
/*       */ 
/*  3379 */       while (ne.hasMore()) {
/*  3380 */         ZSearchResultEntry sr = ne.next();
/*       */         
/*  3382 */         String aliasDomainId = sr.getAttributes().getAttrString("zimbraId");
/*  3383 */         String aliasDomainName = sr.getAttributes().getAttrString("zimbraDomainName");
/*       */         
/*       */ 
/*  3386 */         String aliasDomainDn = sr.getDN();
/*  3387 */         String acctBaseDn = this.mDIT.domainDNToAccountBaseDN(aliasDomainDn);
/*  3388 */         String dynGroupsBaseDn = this.mDIT.domainDNToDynamicGroupsBaseDN(aliasDomainDn);
/*       */         
/*  3390 */         if ((suboridinateCheck) && ((hasSubordinates(zlc, acctBaseDn)) || (hasSubordinates(zlc, dynGroupsBaseDn)))) {
/*  3391 */           throw ServiceException.FAILURE("alias domain " + aliasDomainName + " of doamin " + targetDomain.getName() + " is not empty", null);
/*       */         }
/*       */         
/*       */ 
/*  3395 */         if (aliasDomainId != null) {
/*  3396 */           aliasDomainIds.add(aliasDomainId);
/*       */         }
/*       */       }
/*       */     } finally {
/*  3400 */       ne.close();
/*       */     }
/*       */     
/*  3403 */     return aliasDomainIds;
/*       */   }
/*       */   
/*       */   private boolean hasSubordinates(ZLdapContext zlc, String dn) throws ServiceException {
/*  3407 */     boolean hasSubordinates = false;
/*       */     
/*  3409 */     ZSearchResultEnumeration ne = null;
/*       */     try {
/*  3411 */       ne = this.helper.searchDir(dn, this.filterFactory.hasSubordinates(), ZSearchControls.SEARCH_CTLS_SUBTREE(), zlc, LdapServerType.MASTER);
/*       */       
/*       */ 
/*  3414 */       hasSubordinates = ne.hasMore();
/*       */     } finally {
/*  3416 */       if (ne != null) {
/*  3417 */         ne.close();
/*       */       }
/*       */     }
/*       */     
/*  3421 */     return hasSubordinates;
/*       */   }
/*       */   
/*       */   public void deleteDomainInternal(ZLdapContext zlc, String zimbraId)
/*       */     throws ServiceException
/*       */   {
/*  3427 */     LdapDomain domain = null;
/*  3428 */     String acctBaseDn = null;
/*  3429 */     String dynGroupsBaseDn = null;
/*       */     try {
/*  3431 */       domain = (LdapDomain)getDomainById(zimbraId, zlc);
/*  3432 */       if (domain == null) {
/*  3433 */         throw AccountServiceException.NO_SUCH_DOMAIN(zimbraId);
/*       */       }
/*       */       
/*  3436 */       String name = domain.getName();
/*       */       
/*       */ 
/*  3439 */       acctBaseDn = this.mDIT.domainDNToAccountBaseDN(domain.getDN());
/*  3440 */       if (!acctBaseDn.equals(domain.getDN())) {
/*       */         try {
/*  3442 */           zlc.deleteEntry(acctBaseDn);
/*       */         } catch (LdapException.LdapEntryNotFoundException e) {
/*  3444 */           ZimbraLog.account.info("entry %s not found", new Object[] { acctBaseDn });
/*       */         }
/*       */       }
/*       */       
/*       */ 
/*  3449 */       dynGroupsBaseDn = this.mDIT.domainDNToDynamicGroupsBaseDN(domain.getDN());
/*  3450 */       if (!dynGroupsBaseDn.equals(domain.getDN())) {
/*       */         try {
/*  3452 */           zlc.deleteEntry(dynGroupsBaseDn);
/*       */         } catch (LdapException.LdapEntryNotFoundException e) {
/*  3454 */           ZimbraLog.account.info("entry %s not found", new Object[] { dynGroupsBaseDn });
/*       */         }
/*       */       }
/*       */       try
/*       */       {
/*  3459 */         zlc.deleteEntry(domain.getDN());
/*  3460 */         this.domainCache.remove(domain);
/*       */       }
/*       */       catch (LdapException.LdapContextNotEmptyException e) {
/*  3463 */         this.domainCache.remove(domain);
/*       */         
/*  3465 */         Map<String, String> attrs = new HashMap();
/*  3466 */         attrs.put("-objectClass", "zimbraDomain");
/*       */         
/*  3468 */         for (String key : domain.getAttrs(false).keySet()) {
/*  3469 */           if (key.startsWith("zimbra")) {
/*  3470 */             attrs.put(key, "");
/*       */           }
/*       */         }
/*       */         
/*       */ 
/*       */ 
/*  3476 */         modifyAttrs(domain, attrs, false, false);
/*       */       }
/*       */       
/*  3479 */       String defaultDomain = getConfig().getAttr("zimbraDefaultDomainName", null);
/*  3480 */       if (name.equalsIgnoreCase(defaultDomain)) {
/*       */         try {
/*  3482 */           Map<String, String> attrs = new HashMap();
/*  3483 */           attrs.put("zimbraDefaultDomainName", "");
/*  3484 */           modifyAttrs(getConfig(), attrs);
/*       */         } catch (Exception e) {
/*  3486 */           ZimbraLog.account.warn("unable to remove config attr:zimbraDefaultDomainName", e);
/*       */         }
/*       */       }
/*       */     }
/*       */     catch (LdapException.LdapContextNotEmptyException e) {
/*  3491 */       int maxEntriesToGet = 5;
/*       */       
/*  3493 */       final String doNotReportThisDN = acctBaseDn;
/*  3494 */       final StringBuilder sb = new StringBuilder();
/*  3495 */       sb.append(" (remaining entries: ");
/*       */       
/*  3497 */       SearchLdapOptions.SearchLdapVisitor visitor = new SearchLdapOptions.SearchLdapVisitor()
/*       */       {
/*       */         public void visit(String dn, Map<String, Object> attrs, IAttributes ldapAttrs) {
/*  3500 */           if (!dn.equals(doNotReportThisDN)) {
/*  3501 */             sb.append("[" + dn + "] ");
/*       */           }
/*       */           
/*       */         }
/*  3505 */       };
/*  3506 */       SearchLdapOptions searchOptions = new SearchLdapOptions(acctBaseDn, this.filterFactory.anyEntry(), new String[] { "objectClass" }, maxEntriesToGet, null, ZSearchScope.SEARCH_SCOPE_SUBTREE, visitor);
/*       */       
/*       */ 
/*       */       try
/*       */       {
/*  3511 */         zlc.searchPaged(searchOptions);
/*       */       }
/*       */       catch (LdapException.LdapSizeLimitExceededException lslee) {}catch (ServiceException se)
/*       */       {
/*  3515 */         ZimbraLog.account.warn("unable to get sample entries in non-empty domain " + domain.getName() + " for reporting", se);
/*       */       }
/*       */       
/*  3518 */       sb.append("...)");
/*  3519 */       throw AccountServiceException.DOMAIN_NOT_EMPTY(domain.getName() + sb.toString(), e);
/*       */     } catch (ServiceException e) {
/*  3521 */       throw ServiceException.FAILURE("unable to purge domain: " + zimbraId, e);
/*       */     }
/*       */   }
/*       */   
/*       */   public void renameDomain(String zimbraId, String newDomainName) throws ServiceException
/*       */   {
/*  3527 */     newDomainName = newDomainName.toLowerCase().trim();
/*  3528 */     newDomainName = IDNUtil.toAsciiDomainName(newDomainName);
/*  3529 */     NameUtil.validNewDomainName(newDomainName);
/*       */     
/*  3531 */     ZLdapContext zlc = null;
/*       */     try
/*       */     {
/*  3534 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_DOMAIN);
/*       */       
/*  3536 */       RenameDomain.RenameDomainLdapHelper helper = new RenameDomain.RenameDomainLdapHelper(this, zlc)
/*       */       {
/*       */         private ZLdapContext toZLdapContext()
/*       */         {
/*  3540 */           return LdapClient.toZLdapContext(this.mProv, this.mZlc);
/*       */         }
/*       */         
/*       */ 
/*       */         public void createEntry(String dn, Map<String, Object> attrs)
/*       */           throws ServiceException
/*       */         {
/*  3547 */           ZMutableEntry entry = LdapClient.createMutableEntry();
/*  3548 */           entry.mapToAttrs(attrs);
/*  3549 */           entry.setDN(dn);
/*       */           
/*  3551 */           ZLdapContext ldapContext = toZLdapContext();
/*  3552 */           ldapContext.createEntry(entry);
/*       */         }
/*       */         
/*       */         public void deleteEntry(String dn) throws ServiceException
/*       */         {
/*  3557 */           ZLdapContext ldapContext = toZLdapContext();
/*  3558 */           ldapContext.deleteEntry(dn);
/*       */         }
/*       */         
/*       */         public void renameEntry(String oldDn, String newDn)
/*       */           throws ServiceException
/*       */         {
/*  3564 */           ZLdapContext ldapContext = toZLdapContext();
/*  3565 */           ldapContext.renameEntry(oldDn, newDn);
/*       */         }
/*       */         
/*       */         public void searchDirectory(SearchDirectoryOptions options, NamedEntry.Visitor visitor)
/*       */           throws ServiceException
/*       */         {
/*  3571 */           ((LdapProvisioning)this.mProv).searchDirectory(options, visitor);
/*       */         }
/*       */         
/*       */         public void renameAddressesInAllDistributionLists(Map<String, String> changedPairs)
/*       */         {
/*  3576 */           ((LdapProvisioning)this.mProv).renameAddressesInAllDistributionLists(changedPairs);
/*       */         }
/*       */         
/*       */         public void renameXMPPComponent(String zimbraId, String newName)
/*       */           throws ServiceException
/*       */         {
/*  3582 */           ((LdapProvisioning)this.mProv).renameXMPPComponent(zimbraId, newName);
/*       */         }
/*       */         
/*       */         public Account getAccountById(String id)
/*       */           throws ServiceException
/*       */         {
/*  3588 */           return ((LdapProvisioning)this.mProv).getAccountByQuery(this.mProv.getDIT().mailBranchBaseDN(), ZLdapFilterFactory.getInstance().accountById(id), toZLdapContext(), true);
/*       */         }
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*       */         public DistributionList getDistributionListById(String id)
/*       */           throws ServiceException
/*       */         {
/*  3597 */           return ((LdapProvisioning)this.mProv).getDistributionListByQuery(LdapProvisioning.this.mDIT.mailBranchBaseDN(), LdapProvisioning.this.filterFactory.distributionListById(id), toZLdapContext(), false);
/*       */         }
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*       */         public DynamicGroup getDynamicGroupById(String id)
/*       */           throws ServiceException
/*       */         {
/*  3606 */           return ((LdapProvisioning)this.mProv).getDynamicGroupByQuery(LdapProvisioning.this.filterFactory.dynamicGroupById(id), toZLdapContext(), false);
/*       */         }
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*       */         public void modifyLdapAttrs(Entry entry, Map<String, ? extends Object> attrs)
/*       */           throws ServiceException
/*       */         {
/*  3615 */           ((LdapProvisioning)this.mProv).modifyLdapAttrs(entry, toZLdapContext(), attrs);
/*       */         }
/*       */         
/*       */ 
/*  3619 */       };
/*  3620 */       Domain oldDomain = getDomainById(zimbraId, zlc);
/*  3621 */       if (oldDomain == null) {
/*  3622 */         throw AccountServiceException.NO_SUCH_DOMAIN(zimbraId);
/*       */       }
/*  3624 */       RenameDomain rd = new RenameDomain(this, helper, oldDomain, newDomainName);
/*  3625 */       rd.execute();
/*       */     } finally {
/*  3627 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteCos(String zimbraId) throws ServiceException
/*       */   {
/*  3633 */     LdapCos c = (LdapCos)get(Key.CosBy.id, zimbraId);
/*  3634 */     if (c == null) {
/*  3635 */       throw AccountServiceException.NO_SUCH_COS(zimbraId);
/*       */     }
/*  3637 */     if (c.isDefaultCos()) {
/*  3638 */       throw ServiceException.INVALID_REQUEST("unable to delete default cos", null);
/*       */     }
/*       */     
/*  3641 */     ZLdapContext zlc = null;
/*       */     try {
/*  3643 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_COS);
/*  3644 */       zlc.deleteEntry(c.getDN());
/*  3645 */       this.cosCache.remove(c);
/*       */     } catch (ServiceException e) {
/*  3647 */       throw ServiceException.FAILURE("unable to purge cos: " + zimbraId, e);
/*       */     } finally {
/*  3649 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public ShareLocator get(Key.ShareLocatorBy keyType, String key) throws ServiceException
/*       */   {
/*  3655 */     switch (keyType) {
/*       */     case id: 
/*  3657 */       return getShareLocatorById(key, null, false);
/*       */     }
/*  3659 */     return null;
/*       */   }
/*       */   
/*       */   public ShareLocator createShareLocator(String id, Map<String, Object> attrs)
/*       */     throws ServiceException
/*       */   {
/*  3665 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  3666 */     AttributeManager.getInstance().preModify(attrs, null, callbackContext, true);
/*       */     
/*  3668 */     ZLdapContext zlc = null;
/*       */     try {
/*  3670 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_SHARELOCATOR);
/*       */       
/*  3672 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  3673 */       entry.mapToAttrs(attrs);
/*       */       
/*  3675 */       Set<String> ocs = LdapObjectClass.getShareLocatorObjectClasses(this);
/*  3676 */       entry.addAttr("objectClass", ocs);
/*       */       
/*  3678 */       entry.setAttr("cn", id);
/*  3679 */       String dn = this.mDIT.shareLocatorIdToDN(id);
/*       */       
/*  3681 */       entry.setDN(dn);
/*  3682 */       zlc.createEntry(entry);
/*       */       
/*  3684 */       ShareLocator shloc = getShareLocatorById(id, zlc, true);
/*  3685 */       AttributeManager.getInstance().postModify(attrs, shloc, callbackContext);
/*  3686 */       return shloc;
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  3689 */       throw AccountServiceException.SHARE_LOCATOR_EXISTS(id);
/*       */     } catch (LdapException e) {
/*  3691 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  3693 */       throw e;
/*       */     } catch (ServiceException e) {
/*  3695 */       throw ServiceException.FAILURE("unable to create share locator: " + id, e);
/*       */     } finally {
/*  3697 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteShareLocator(String id) throws ServiceException
/*       */   {
/*  3703 */     LdapShareLocator shloc = (LdapShareLocator)get(Key.ShareLocatorBy.id, id);
/*  3704 */     if (shloc == null) {
/*  3705 */       throw AccountServiceException.NO_SUCH_SHARE_LOCATOR(id);
/*       */     }
/*  3707 */     ZLdapContext zlc = null;
/*       */     try {
/*  3709 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_SHARELOCATOR);
/*  3710 */       zlc.deleteEntry(shloc.getDN());
/*  3711 */       this.shareLocatorCache.remove(shloc);
/*       */     } catch (ServiceException e) {
/*  3713 */       throw ServiceException.FAILURE("unable to delete share locator: " + id, e);
/*       */     } finally {
/*  3715 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public Server createServer(String name, Map<String, Object> serverAttrs)
/*       */     throws ServiceException
/*       */   {
/*  3722 */     name = name.toLowerCase().trim();
/*       */     
/*  3724 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  3725 */     AttributeManager.getInstance().preModify(serverAttrs, null, callbackContext, true);
/*       */     
/*  3727 */     String authHost = (String)serverAttrs.get("zimbraMtaAuthHost");
/*  3728 */     if (authHost != null) {
/*  3729 */       serverAttrs.put("zimbraMtaAuthURL", com.zimbra.cs.httpclient.URLUtil.getMtaAuthURL(authHost));
/*       */     }
/*       */     
/*  3732 */     ZLdapContext zlc = null;
/*       */     try {
/*  3734 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_SERVER);
/*       */       
/*  3736 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  3737 */       entry.mapToAttrs(serverAttrs);
/*       */       
/*  3739 */       Set<String> ocs = LdapObjectClass.getServerObjectClasses(this);
/*  3740 */       entry.addAttr("objectClass", ocs);
/*       */       
/*  3742 */       String zimbraIdStr = LdapUtil.generateUUID();
/*  3743 */       entry.setAttr("zimbraId", zimbraIdStr);
/*  3744 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*  3745 */       entry.setAttr("cn", name);
/*  3746 */       String dn = this.mDIT.serverNameToDN(name);
/*       */       
/*  3748 */       if (!entry.hasAttribute("zimbraServiceHostname")) {
/*  3749 */         entry.setAttr("zimbraServiceHostname", name);
/*       */       }
/*       */       
/*  3752 */       entry.setDN(dn);
/*  3753 */       zlc.createEntry(entry);
/*       */       
/*  3755 */       Server server = getServerById(zimbraIdStr, zlc, true);
/*  3756 */       AttributeManager.getInstance().postModify(serverAttrs, server, callbackContext);
/*  3757 */       return server;
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  3760 */       throw AccountServiceException.SERVER_EXISTS(name);
/*       */     } catch (LdapException e) {
/*  3762 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  3764 */       throw e;
/*       */     } catch (ServiceException e) {
/*  3766 */       throw ServiceException.FAILURE("unable to create server: " + name, e);
/*       */     } finally {
/*  3768 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   private Server getServerByQuery(ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*       */     try {
/*  3775 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.serverBaseDN(), filter, initZlc, false);
/*  3776 */       if (sr != null) {
/*  3777 */         return new LdapServer(sr.getDN(), sr.getAttributes(), getConfig().getServerDefaults(), this);
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  3780 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getServerByQuery", e);
/*       */     } catch (ServiceException e) {
/*  3782 */       throw ServiceException.FAILURE("unable to lookup server via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  3785 */     return null;
/*       */   }
/*       */   
/*       */   private Server getServerById(String zimbraId, ZLdapContext zlc, boolean nocache) throws ServiceException
/*       */   {
/*  3790 */     if (zimbraId == null)
/*  3791 */       return null;
/*  3792 */     Server s = null;
/*  3793 */     if (!nocache)
/*  3794 */       s = (Server)this.serverCache.getById(zimbraId);
/*  3795 */     if (s == null) {
/*  3796 */       s = getServerByQuery(this.filterFactory.serverById(zimbraId), zlc);
/*  3797 */       this.serverCache.put(s);
/*       */     }
/*  3799 */     return s;
/*       */   }
/*       */   
/*       */   private AlwaysOnCluster getAlwaysOnClusterByQuery(ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*       */     try {
/*  3805 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.alwaysOnClusterBaseDN(), filter, initZlc, false);
/*  3806 */       if (sr != null) {
/*  3807 */         return new LdapAlwaysOnCluster(sr.getDN(), sr.getAttributes(), null, this);
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  3810 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getAlwaysOnClusterByQuery", e);
/*       */     } catch (ServiceException e) {
/*  3812 */       throw ServiceException.FAILURE("unable to lookup alwaysOnCluster via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  3815 */     return null;
/*       */   }
/*       */   
/*       */   private AlwaysOnCluster getAlwaysOnClusterById(String zimbraId, ZLdapContext zlc, boolean nocache) throws ServiceException
/*       */   {
/*  3820 */     if (zimbraId == null)
/*  3821 */       return null;
/*  3822 */     AlwaysOnCluster c = null;
/*  3823 */     if (!nocache)
/*  3824 */       c = (AlwaysOnCluster)this.alwaysOnClusterCache.getById(zimbraId);
/*  3825 */     if (c == null) {
/*  3826 */       c = getAlwaysOnClusterByQuery(this.filterFactory.alwaysOnClusterById(zimbraId), zlc);
/*  3827 */       this.alwaysOnClusterCache.put(c);
/*       */     }
/*  3829 */     return c;
/*       */   }
/*       */   
/*       */   private ShareLocator getShareLocatorByQuery(ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*       */     try {
/*  3835 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.shareLocatorBaseDN(), filter, initZlc, false);
/*  3836 */       if (sr != null) {
/*  3837 */         return new LdapShareLocator(sr.getDN(), sr.getAttributes(), this);
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  3840 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getShareLocatorByQuery", e);
/*       */     } catch (ServiceException e) {
/*  3842 */       throw ServiceException.FAILURE("unable to lookup share locator via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  3845 */     return null;
/*       */   }
/*       */   
/*       */   private ShareLocator getShareLocatorById(String id, ZLdapContext zlc, boolean nocache) throws ServiceException
/*       */   {
/*  3850 */     if (id == null)
/*  3851 */       return null;
/*  3852 */     ShareLocator shloc = null;
/*  3853 */     if (!nocache)
/*  3854 */       shloc = (ShareLocator)this.shareLocatorCache.getById(id);
/*  3855 */     if (shloc == null) {
/*  3856 */       shloc = getShareLocatorByQuery(this.filterFactory.shareLocatorById(id), zlc);
/*  3857 */       this.shareLocatorCache.put(shloc);
/*       */     }
/*  3859 */     return shloc;
/*       */   }
/*       */   
/*       */   public Server get(Key.ServerBy keyType, String key) throws ServiceException
/*       */   {
/*  3864 */     switch (keyType) {
/*       */     case name: 
/*  3866 */       return getServerByNameInternal(key);
/*       */     case id: 
/*  3868 */       return getServerByIdInternal(key);
/*       */     case serviceHostname: 
/*  3870 */       List<Server> servers = getAllServers();
/*  3871 */       for (Server server : servers)
/*       */       {
/*  3873 */         if (key.equalsIgnoreCase(server.getAttr("zimbraServiceHostname", ""))) {
/*  3874 */           return server;
/*       */         }
/*       */       }
/*  3877 */       return null;
/*       */     }
/*  3879 */     return null;
/*       */   }
/*       */   
/*       */   private Server getServerByIdInternal(String zimbraId) throws ServiceException
/*       */   {
/*  3884 */     return getServerById(zimbraId, null, false);
/*       */   }
/*       */   
/*       */   private Server getServerByNameInternal(String name) throws ServiceException {
/*  3888 */     return getServerByName(name, false);
/*       */   }
/*       */   
/*       */   private Server getServerByName(String name, boolean nocache) throws ServiceException {
/*  3892 */     if (!nocache) {
/*  3893 */       Server s = (Server)this.serverCache.getByName(name);
/*  3894 */       if (s != null) {
/*  3895 */         return s;
/*       */       }
/*       */     }
/*       */     try {
/*  3899 */       String dn = this.mDIT.serverNameToDN(name);
/*  3900 */       ZAttributes attrs = this.helper.getAttributes(LdapUsage.GET_SERVER, dn);
/*  3901 */       LdapServer s = new LdapServer(dn, attrs, getConfig().getServerDefaults(), this);
/*  3902 */       this.serverCache.put(s);
/*  3903 */       return s;
/*       */     } catch (LdapException.LdapEntryNotFoundException e) {
/*  3905 */       return null;
/*       */     } catch (ServiceException e) {
/*  3907 */       throw ServiceException.FAILURE("unable to lookup server by name: " + name + " message: " + e.getMessage(), e);
/*       */     }
/*       */   }
/*       */   
/*       */   private AlwaysOnCluster getAlwaysOnClusterByNameInternal(String name) throws ServiceException {
/*  3912 */     return getAlwaysOnClusterByName(name, false);
/*       */   }
/*       */   
/*       */   private AlwaysOnCluster getAlwaysOnClusterByName(String name, boolean nocache) throws ServiceException {
/*  3916 */     if (!nocache) {
/*  3917 */       AlwaysOnCluster c = (AlwaysOnCluster)this.alwaysOnClusterCache.getByName(name);
/*  3918 */       if (c != null) {
/*  3919 */         return c;
/*       */       }
/*       */     }
/*       */     try {
/*  3923 */       String dn = this.mDIT.alwaysOnClusterNameToDN(name);
/*  3924 */       ZAttributes attrs = this.helper.getAttributes(LdapUsage.GET_ALWAYSONCLUSTER, dn);
/*  3925 */       LdapAlwaysOnCluster c = new LdapAlwaysOnCluster(dn, attrs, null, this);
/*  3926 */       this.alwaysOnClusterCache.put(c);
/*  3927 */       return c;
/*       */     } catch (LdapException.LdapEntryNotFoundException e) {
/*  3929 */       return null;
/*       */     } catch (ServiceException e) {
/*  3931 */       throw ServiceException.FAILURE("unable to lookup alwaysOnCluster by name: " + name + " message: " + e.getMessage(), e);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<Server> getAllServers() throws ServiceException
/*       */   {
/*  3937 */     return getAllServers((String)null);
/*       */   }
/*       */   
/*       */   public List<Server> getAllServers(String service) throws ServiceException
/*       */   {
/*  3942 */     List<Server> result = new ArrayList();
/*       */     ZLdapFilter filter;
/*       */     ZLdapFilter filter;
/*  3945 */     if (service != null) {
/*  3946 */       filter = this.filterFactory.serverByService(service);
/*       */     } else {
/*  3948 */       filter = this.filterFactory.allServers();
/*       */     }
/*       */     try
/*       */     {
/*  3952 */       Map<String, Object> serverDefaults = getConfig().getServerDefaults();
/*       */       
/*  3954 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.serverBaseDN(), filter, ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*  3956 */       while (ne.hasMore()) {
/*  3957 */         ZSearchResultEntry sr = ne.next();
/*  3958 */         LdapServer s = new LdapServer(sr.getDN(), sr.getAttributes(), serverDefaults, this);
/*       */         
/*  3960 */         result.add(s);
/*       */       }
/*  3962 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  3964 */       throw ServiceException.FAILURE("unable to list all servers", e);
/*       */     }
/*       */     
/*  3967 */     if (result.size() > 0)
/*  3968 */       this.serverCache.put(result, true);
/*  3969 */     Collections.sort(result);
/*  3970 */     return result;
/*       */   }
/*       */   
/*       */   public List<Server> getAllServers(String service, String clusterId) throws ServiceException
/*       */   {
/*  3975 */     List<Server> result = new ArrayList();
/*       */     
/*  3977 */     ZLdapFilter filter = this.filterFactory.serverByServiceAndAlwaysOnCluster(service, clusterId);
/*       */     try
/*       */     {
/*  3980 */       Map<String, Object> serverDefaults = getConfig().getServerDefaults();
/*       */       
/*  3982 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.serverBaseDN(), filter, ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*  3984 */       while (ne.hasMore()) {
/*  3985 */         ZSearchResultEntry sr = ne.next();
/*  3986 */         LdapServer s = new LdapServer(sr.getDN(), sr.getAttributes(), serverDefaults, this);
/*       */         
/*  3988 */         result.add(s);
/*       */       }
/*  3990 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  3992 */       throw ServiceException.FAILURE("unable to list all servers by cluster id", e);
/*       */     }
/*       */     
/*  3995 */     Collections.sort(result);
/*  3996 */     return result;
/*       */   }
/*       */   
/*       */   public AlwaysOnCluster createAlwaysOnCluster(String name, Map<String, Object> clusterAttrs)
/*       */     throws ServiceException
/*       */   {
/*  4002 */     name = name.toLowerCase().trim();
/*       */     
/*  4004 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  4005 */     AttributeManager.getInstance().preModify(clusterAttrs, null, callbackContext, true);
/*       */     
/*  4007 */     ZLdapContext zlc = null;
/*       */     try {
/*  4009 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_SERVER);
/*       */       
/*  4011 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  4012 */       entry.mapToAttrs(clusterAttrs);
/*       */       
/*  4014 */       Set<String> ocs = LdapObjectClass.getAlwaysOnClusterObjectClasses(this);
/*  4015 */       entry.addAttr("objectClass", ocs);
/*       */       
/*  4017 */       String zimbraIdStr = LdapUtil.generateUUID();
/*  4018 */       entry.setAttr("zimbraId", zimbraIdStr);
/*  4019 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*  4020 */       entry.setAttr("cn", name);
/*  4021 */       String dn = this.mDIT.alwaysOnClusterNameToDN(name);
/*  4022 */       entry.setDN(dn);
/*  4023 */       zlc.createEntry(entry);
/*       */       
/*  4025 */       AlwaysOnCluster cluster = getAlwaysOnClusterById(zimbraIdStr, zlc, true);
/*  4026 */       AttributeManager.getInstance().postModify(clusterAttrs, cluster, callbackContext);
/*  4027 */       return cluster;
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  4030 */       throw AccountServiceException.ALWAYSONCLUSTER_EXISTS(name);
/*       */     } catch (LdapException e) {
/*  4032 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  4034 */       throw e;
/*       */     } catch (ServiceException e) {
/*  4036 */       throw ServiceException.FAILURE("unable to create akwaysOnCluster: " + name, e);
/*       */     } finally {
/*  4038 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<AlwaysOnCluster> getAllAlwaysOnClusters() throws ServiceException
/*       */   {
/*  4044 */     List<AlwaysOnCluster> result = new ArrayList();
/*       */     
/*  4046 */     ZLdapFilter filter = this.filterFactory.allAlwaysOnClusters();
/*       */     
/*       */     try
/*       */     {
/*  4050 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.alwaysOnClusterBaseDN(), filter, ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*  4052 */       while (ne.hasMore()) {
/*  4053 */         ZSearchResultEntry sr = ne.next();
/*  4054 */         LdapAlwaysOnCluster c = new LdapAlwaysOnCluster(sr.getDN(), sr.getAttributes(), null, this);
/*       */         
/*  4056 */         result.add(c);
/*       */       }
/*  4058 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  4060 */       throw ServiceException.FAILURE("unable to list all alwaysOnClusters", e);
/*       */     }
/*       */     
/*  4063 */     if (result.size() > 0)
/*  4064 */       this.alwaysOnClusterCache.put(result, true);
/*  4065 */     Collections.sort(result);
/*  4066 */     return result;
/*       */   }
/*       */   
/*       */   private AlwaysOnCluster getAlwaysOnClusterByIdInternal(String zimbraId) throws ServiceException {
/*  4070 */     return getAlwaysOnClusterById(zimbraId, null, false);
/*       */   }
/*       */   
/*       */   public AlwaysOnCluster get(Key.AlwaysOnClusterBy keyType, String key) throws ServiceException
/*       */   {
/*  4075 */     switch (keyType) {
/*       */     case id: 
/*  4077 */       return getAlwaysOnClusterByIdInternal(key);
/*       */     case name: 
/*  4079 */       return getAlwaysOnClusterByNameInternal(key);
/*       */     }
/*  4081 */     return null;
/*       */   }
/*       */   
/*       */   private List<Cos> searchCOS(ZLdapFilter filter, ZLdapContext initZlc)
/*       */     throws ServiceException
/*       */   {
/*  4087 */     List<Cos> result = new ArrayList();
/*       */     try {
/*  4089 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.cosBaseDN(), filter, ZSearchControls.SEARCH_CTLS_SUBTREE(), initZlc, LdapServerType.REPLICA);
/*       */       
/*  4091 */       while (ne.hasMore()) {
/*  4092 */         ZSearchResultEntry sr = ne.next();
/*  4093 */         result.add(new LdapCos(sr.getDN(), sr.getAttributes(), this));
/*       */       }
/*  4095 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  4097 */       throw ServiceException.FAILURE("unable to lookup cos via query: " + filter.toFilterString() + " message: " + e.getMessage(), e);
/*       */     }
/*       */     
/*  4100 */     return result;
/*       */   }
/*       */   
/*       */   private void removeServerFromAllCOSes(String serverId, String serverName, ZLdapContext initZlc) {
/*  4104 */     List<Cos> coses = null;
/*       */     try {
/*  4106 */       coses = searchCOS(this.filterFactory.cosesByMailHostPool(serverId), initZlc);
/*  4107 */       for (Cos cos : coses) {
/*  4108 */         Map<String, String> attrs = new HashMap();
/*  4109 */         attrs.put("-zimbraMailHostPool", serverId);
/*  4110 */         ZimbraLog.account.info("Removing zimbraMailHostPool " + serverId + "(" + serverName + ") from cos " + cos.getName());
/*       */         
/*  4112 */         modifyAttrs(cos, attrs);
/*       */         
/*  4114 */         this.cosCache.remove((LdapCos)cos);
/*       */       }
/*       */     } catch (ServiceException se) {
/*  4117 */       ZimbraLog.account.warn("unable to remove " + serverId + " from all COSes ", se);
/*  4118 */       return;
/*       */     }
/*       */   }
/*       */   
/*       */   private static class CountingVisitor extends SearchLdapOptions.SearchLdapVisitor
/*       */   {
/*  4124 */     long numAccts = 0L;
/*       */     
/*       */     CountingVisitor() {
/*  4127 */       super();
/*       */     }
/*       */     
/*       */     public void visit(String dn, IAttributes ldapAttrs)
/*       */     {
/*  4132 */       this.numAccts += 1L;
/*       */     }
/*       */     
/*       */     long getNumAccts() {
/*  4136 */       return this.numAccts;
/*       */     }
/*       */   }
/*       */   
/*       */   private long getNumAccountsOnServer(Server server) throws ServiceException {
/*  4141 */     ZLdapFilter filter = this.filterFactory.accountsHomedOnServer(server.getServiceHostname());
/*  4142 */     String base = this.mDIT.mailBranchBaseDN();
/*  4143 */     String[] attrs = { "zimbraId" };
/*       */     
/*  4145 */     CountingVisitor visitor = new CountingVisitor();
/*       */     
/*  4147 */     searchLdapOnMaster(base, filter, attrs, visitor);
/*       */     
/*  4149 */     return visitor.getNumAccts();
/*       */   }
/*       */   
/*       */   public void deleteServer(String zimbraId) throws ServiceException
/*       */   {
/*  4154 */     LdapServer server = (LdapServer)getServerByIdInternal(zimbraId);
/*  4155 */     if (server == null) {
/*  4156 */       throw AccountServiceException.NO_SUCH_SERVER(zimbraId);
/*       */     }
/*       */     
/*  4159 */     long numAcctsOnServer = getNumAccountsOnServer(server);
/*  4160 */     if (numAcctsOnServer != 0L) {
/*  4161 */       throw ServiceException.INVALID_REQUEST("There are " + numAcctsOnServer + " account(s) on this server.", null);
/*       */     }
/*       */     
/*       */ 
/*  4165 */     ZLdapContext zlc = null;
/*       */     try {
/*  4167 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_SERVER);
/*  4168 */       removeServerFromAllCOSes(zimbraId, server.getName(), zlc);
/*  4169 */       zlc.deleteEntry(server.getDN());
/*  4170 */       this.serverCache.remove(server);
/*       */     } catch (ServiceException e) {
/*  4172 */       throw ServiceException.FAILURE("unable to purge server: " + zimbraId, e);
/*       */     } finally {
/*  4174 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteAlwaysOnCluster(String zimbraId) throws ServiceException
/*       */   {
/*  4180 */     LdapAlwaysOnCluster cluster = (LdapAlwaysOnCluster)getAlwaysOnClusterByIdInternal(zimbraId);
/*  4181 */     if (cluster == null) {
/*  4182 */       throw AccountServiceException.NO_SUCH_ALWAYSONCLUSTER(zimbraId);
/*       */     }
/*  4184 */     ZLdapContext zlc = null;
/*       */     try {
/*  4186 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_ALWAYSONCLUSTER);
/*  4187 */       zlc.deleteEntry(cluster.getDN());
/*  4188 */       this.alwaysOnClusterCache.remove(cluster);
/*       */     } catch (ServiceException e) {
/*  4190 */       throw ServiceException.FAILURE("unable to purge alwaysOnCluster: " + zimbraId, e);
/*       */     } finally {
/*  4192 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public DistributionList createDistributionList(String listAddress, Map<String, Object> listAttrs)
/*       */     throws ServiceException
/*       */   {
/*  4203 */     return createDistributionList(listAddress, listAttrs, null);
/*       */   }
/*       */   
/*       */ 
/*       */   private DistributionList createDistributionList(String listAddress, Map<String, Object> listAttrs, Account creator)
/*       */     throws ServiceException
/*       */   {
/*  4210 */     SpecialAttrs specialAttrs = this.mDIT.handleSpecialAttrs(listAttrs);
/*  4211 */     String baseDn = specialAttrs.getLdapBaseDn();
/*       */     
/*  4213 */     listAddress = listAddress.toLowerCase().trim();
/*       */     
/*  4215 */     String[] parts = listAddress.split("@");
/*  4216 */     if (parts.length != 2) {
/*  4217 */       throw ServiceException.INVALID_REQUEST("must be valid list address: " + listAddress, null);
/*       */     }
/*  4219 */     String localPart = parts[0];
/*  4220 */     String domain = parts[1];
/*  4221 */     domain = IDNUtil.toAsciiDomainName(domain);
/*  4222 */     listAddress = localPart + "@" + domain;
/*       */     
/*  4224 */     validEmailAddress(listAddress);
/*       */     
/*  4226 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  4227 */     callbackContext.setCreatingEntryName(listAddress);
/*  4228 */     AttributeManager.getInstance().preModify(listAttrs, null, callbackContext, true);
/*       */     
/*  4230 */     ZLdapContext zlc = null;
/*       */     try {
/*  4232 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_DISTRIBUTIONLIST);
/*       */       
/*  4234 */       Domain d = getDomainByAsciiName(domain, zlc);
/*  4235 */       if (d == null) {
/*  4236 */         throw AccountServiceException.NO_SUCH_DOMAIN(domain);
/*       */       }
/*  4238 */       if (!d.isLocal()) {
/*  4239 */         throw ServiceException.INVALID_REQUEST("domain type must be local", null);
/*       */       }
/*       */       
/*  4242 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  4243 */       entry.mapToAttrs(listAttrs);
/*       */       
/*  4245 */       Set<String> ocs = LdapObjectClass.getDistributionListObjectClasses(this);
/*  4246 */       entry.addAttr("objectClass", ocs);
/*       */       
/*  4248 */       String zimbraIdStr = LdapUtil.generateUUID();
/*  4249 */       entry.setAttr("zimbraId", zimbraIdStr);
/*  4250 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*  4251 */       entry.setAttr("mail", listAddress);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  4257 */       entry.setAttr("zimbraMailAlias", listAddress);
/*       */       
/*       */ 
/*  4260 */       if (!entry.hasAttribute("zimbraMailStatus")) {
/*  4261 */         entry.setAttr("zimbraMailStatus", "enabled");
/*       */       }
/*       */       
/*  4264 */       String displayName = entry.getAttrString("displayName");
/*  4265 */       if (displayName != null) {
/*  4266 */         entry.setAttr("cn", displayName);
/*       */       }
/*       */       
/*  4269 */       entry.setAttr("uid", localPart);
/*       */       
/*  4271 */       setGroupHomeServer(entry, creator);
/*       */       
/*  4273 */       String dn = this.mDIT.distributionListDNCreate(baseDn, entry.getAttributes(), localPart, domain);
/*  4274 */       entry.setDN(dn);
/*       */       
/*  4276 */       zlc.createEntry(entry);
/*       */       
/*  4278 */       DistributionList dlist = getDLBasic(Key.DistributionListBy.id, zimbraIdStr, zlc);
/*       */       
/*  4280 */       if (dlist != null) {
/*  4281 */         AttributeManager.getInstance().postModify(listAttrs, dlist, callbackContext);
/*  4282 */         removeExternalAddrsFromAllDynamicGroups(dlist.getAllAddrsSet(), zlc);
/*  4283 */         this.allDLs.addGroup(dlist);
/*       */       } else {
/*  4285 */         throw ServiceException.FAILURE("unable to get distribution list after creating LDAP entry: " + listAddress, null);
/*       */       }
/*       */       
/*  4288 */       return dlist;
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  4291 */       throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(listAddress);
/*       */     } catch (LdapException e) {
/*  4293 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  4295 */       throw e;
/*       */     } catch (ServiceException e) {
/*  4297 */       throw ServiceException.FAILURE("unable to create distribution list: " + listAddress, e);
/*       */     } finally {
/*  4299 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<DistributionList> getDistributionLists(DistributionList list, boolean directOnly, Map<String, String> via)
/*       */     throws ServiceException
/*       */   {
/*  4306 */     return getContainingDistributionLists(list, directOnly, via);
/*       */   }
/*       */   
/*       */   private DistributionList getDistributionListByQuery(String base, ZLdapFilter filter, ZLdapContext initZlc, boolean basicAttrsOnly)
/*       */     throws ServiceException
/*       */   {
/*  4312 */     String[] returnAttrs = basicAttrsOnly ? this.BASIC_DL_ATTRS : null;
/*       */     
/*  4314 */     DistributionList dl = null;
/*       */     try {
/*  4316 */       ZSearchControls searchControls = ZSearchControls.createSearchControls(ZSearchScope.SEARCH_SCOPE_SUBTREE, 0, returnAttrs);
/*       */       
/*       */ 
/*  4319 */       ZSearchResultEnumeration ne = this.helper.searchDir(base, filter, searchControls, initZlc, LdapServerType.REPLICA);
/*       */       
/*  4321 */       if (ne.hasMore()) {
/*  4322 */         ZSearchResultEntry sr = ne.next();
/*  4323 */         dl = makeDistributionList(sr.getDN(), sr.getAttributes(), basicAttrsOnly);
/*       */       }
/*  4325 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  4327 */       throw ServiceException.FAILURE("unable to lookup distribution list via query: " + filter.toFilterString() + " message: " + e.getMessage(), e);
/*       */     }
/*       */     
/*  4330 */     return dl;
/*       */   }
/*       */   
/*       */   public void renameDistributionList(String zimbraId, String newEmail) throws ServiceException
/*       */   {
/*  4335 */     newEmail = IDNUtil.toAsciiEmail(newEmail);
/*  4336 */     validEmailAddress(newEmail);
/*       */     
/*  4338 */     boolean domainChanged = false;
/*  4339 */     ZLdapContext zlc = null;
/*       */     try {
/*  4341 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_DISTRIBUTIONLIST);
/*       */       
/*  4343 */       LdapDistributionList dl = (LdapDistributionList)getDistributionListById(zimbraId, zlc);
/*  4344 */       if (dl == null) {
/*  4345 */         throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
/*       */       }
/*       */       
/*  4348 */       this.groupCache.remove(dl);
/*       */       
/*  4350 */       String oldEmail = dl.getName();
/*  4351 */       String oldDomain = EmailUtil.getValidDomainPart(oldEmail);
/*       */       
/*  4353 */       newEmail = newEmail.toLowerCase().trim();
/*  4354 */       String[] parts = EmailUtil.getLocalPartAndDomain(newEmail);
/*  4355 */       if (parts == null)
/*  4356 */         throw ServiceException.INVALID_REQUEST("bad value for newName", null);
/*  4357 */       String newLocal = parts[0];
/*  4358 */       String newDomain = parts[1];
/*       */       
/*  4360 */       domainChanged = !oldDomain.equals(newDomain);
/*       */       
/*  4362 */       Domain domain = getDomainByAsciiName(newDomain, zlc);
/*  4363 */       if (domain == null) {
/*  4364 */         throw AccountServiceException.NO_SUCH_DOMAIN(newDomain);
/*       */       }
/*       */       
/*  4367 */       if (domainChanged)
/*       */       {
/*  4369 */         if (!domain.isLocal()) {
/*  4370 */           throw ServiceException.INVALID_REQUEST("domain type must be local", null);
/*       */         }
/*       */       }
/*       */       
/*  4374 */       Map<String, Object> attrs = new HashMap();
/*       */       
/*  4376 */       ReplaceAddressResult replacedMails = replaceMailAddresses(dl, "mail", oldEmail, newEmail);
/*  4377 */       if (replacedMails.newAddrs().length == 0)
/*       */       {
/*  4379 */         attrs.put("mail", newEmail);
/*       */       } else {
/*  4381 */         attrs.put("mail", replacedMails.newAddrs());
/*       */       }
/*       */       
/*  4384 */       ReplaceAddressResult replacedAliases = replaceMailAddresses(dl, "zimbraMailAlias", oldEmail, newEmail);
/*  4385 */       if (replacedAliases.newAddrs().length > 0) {
/*  4386 */         attrs.put("zimbraMailAlias", replacedAliases.newAddrs());
/*       */         
/*  4388 */         String newDomainDN = this.mDIT.domainToAccountSearchDN(newDomain);
/*       */         
/*       */ 
/*  4391 */         if ((domainChanged) && (addressExistsUnderDN(zlc, newDomainDN, replacedAliases.newAddrs()))) {
/*  4392 */           throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
/*       */         }
/*       */       }
/*       */       
/*  4396 */       ReplaceAddressResult replacedAllowAddrForDelegatedSender = replaceMailAddresses(dl, "zimbraPrefAllowAddressForDelegatedSender", oldEmail, newEmail);
/*       */       
/*       */ 
/*  4399 */       if (replacedAllowAddrForDelegatedSender.newAddrs().length > 0) {
/*  4400 */         attrs.put("zimbraPrefAllowAddressForDelegatedSender", replacedAllowAddrForDelegatedSender.newAddrs());
/*       */       }
/*       */       
/*       */ 
/*  4404 */       String oldDn = dl.getDN();
/*  4405 */       String newDn = this.mDIT.distributionListDNRename(oldDn, newLocal, domain.getName());
/*  4406 */       boolean dnChanged = !oldDn.equals(newDn);
/*       */       
/*  4408 */       if (dnChanged)
/*       */       {
/*       */ 
/*       */ 
/*  4412 */         attrs.remove("uid");
/*       */ 
/*       */       }
/*       */       else
/*       */       {
/*       */ 
/*  4418 */         attrs.put("uid", newLocal);
/*       */       }
/*       */       
/*       */ 
/*  4422 */       if (dnChanged) {
/*  4423 */         zlc.renameEntry(oldDn, newDn);
/*       */       }
/*       */       
/*  4426 */       dl = (LdapDistributionList)getDistributionListById(zimbraId, zlc);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  4431 */       renameAddressesInAllDistributionLists(oldEmail, newEmail, replacedAliases);
/*       */       
/*       */ 
/*       */ 
/*  4435 */       if (domainChanged) {
/*  4436 */         String newUid = dl.getAttr("uid");
/*  4437 */         moveAliases(zlc, replacedAliases, newDomain, newUid, oldDn, newDn, oldDomain, newDomain);
/*       */       }
/*       */       
/*       */ 
/*       */       try
/*       */       {
/*  4443 */         modifyAttrsInternal(dl, zlc, attrs);
/*       */       } catch (ServiceException e) {
/*  4445 */         ZimbraLog.account.error("distribution list renamed to " + newLocal + " but failed to move old name's LDAP attributes", e);
/*       */         
/*  4447 */         throw e;
/*       */       }
/*       */       
/*  4450 */       removeExternalAddrsFromAllDynamicGroups(dl.getAllAddrsSet(), zlc);
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  4453 */       throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
/*       */     } catch (LdapException e) {
/*  4455 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  4457 */       throw e;
/*       */     } catch (ServiceException e) {
/*  4459 */       throw ServiceException.FAILURE("unable to rename distribution list: " + zimbraId, e);
/*       */     } finally {
/*  4461 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/*  4464 */     if (domainChanged) {
/*  4465 */       PermissionCache.invalidateCache();
/*       */     }
/*       */   }
/*       */   
/*       */   public DistributionList get(Key.DistributionListBy keyType, String key)
/*       */     throws ServiceException
/*       */   {
/*  4472 */     switch (keyType) {
/*       */     case id: 
/*  4474 */       return getDistributionListByIdInternal(key);
/*       */     case name: 
/*  4476 */       DistributionList dl = getDistributionListByNameInternal(key);
/*  4477 */       if (dl == null) {
/*  4478 */         String localDomainAddr = getEmailAddrByDomainAlias(key);
/*  4479 */         if (localDomainAddr != null) {
/*  4480 */           dl = getDistributionListByNameInternal(localDomainAddr);
/*       */         }
/*       */       }
/*  4483 */       return dl;
/*       */     }
/*  4485 */     return null;
/*       */   }
/*       */   
/*       */   private DistributionList getDistributionListById(String zimbraId, ZLdapContext zlc)
/*       */     throws ServiceException
/*       */   {
/*  4491 */     return getDistributionListByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.distributionListById(zimbraId), zlc, false);
/*       */   }
/*       */   
/*       */ 
/*       */   private DistributionList getDistributionListByIdInternal(String zimbraId)
/*       */     throws ServiceException
/*       */   {
/*  4498 */     return getDistributionListById(zimbraId, null);
/*       */   }
/*       */   
/*       */   public void deleteDistributionList(String zimbraId) throws ServiceException
/*       */   {
/*  4503 */     LdapDistributionList dl = (LdapDistributionList)getDistributionListByIdInternal(zimbraId);
/*  4504 */     if (dl == null) {
/*  4505 */       throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
/*       */     }
/*       */     
/*  4508 */     deleteDistributionList(dl);
/*       */   }
/*       */   
/*       */   private void deleteDistributionList(LdapDistributionList dl) throws ServiceException {
/*  4512 */     String zimbraId = dl.getId();
/*       */     
/*       */ 
/*       */ 
/*  4516 */     Set<String> addrs = new HashSet(dl.getMultiAttrSet("mail"));
/*       */     
/*       */ 
/*  4519 */     removeAddressFromAllDistributionLists(dl.getName());
/*       */     
/*       */ 
/*  4522 */     String[] aliases = dl.getAliases();
/*  4523 */     if (aliases != null) {
/*  4524 */       String dlName = dl.getName();
/*  4525 */       for (int i = 0; i < aliases.length; i++)
/*       */       {
/*       */ 
/*  4528 */         if (!dlName.equalsIgnoreCase(aliases[i])) {
/*  4529 */           removeAlias(dl, aliases[i]);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*       */     try
/*       */     {
/*  4536 */       RightCommand.revokeAllRights(this, GranteeType.GT_GROUP, zimbraId);
/*       */     }
/*       */     catch (ServiceException e) {
/*  4539 */       ZimbraLog.account.warn("cannot revoke grants", e);
/*       */     }
/*       */     
/*  4542 */     ZLdapContext zlc = null;
/*       */     try {
/*  4544 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_DISTRIBUTIONLIST);
/*  4545 */       zlc.deleteEntry(dl.getDN());
/*  4546 */       this.groupCache.remove(dl);
/*  4547 */       this.allDLs.removeGroup(addrs);
/*       */     } catch (ServiceException e) {
/*  4549 */       throw ServiceException.FAILURE("unable to purge distribution list: " + zimbraId, e);
/*       */     } finally {
/*  4551 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/*  4554 */     PermissionCache.invalidateCache();
/*       */   }
/*       */   
/*       */   private DistributionList getDistributionListByNameInternal(String listAddress) throws ServiceException
/*       */   {
/*  4559 */     listAddress = IDNUtil.toAsciiEmail(listAddress);
/*       */     
/*  4561 */     return getDistributionListByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.distributionListByName(listAddress), null, false);
/*       */   }
/*       */   
/*       */ 
/*       */   public boolean isDistributionList(String addr)
/*       */   {
/*  4567 */     boolean isDL = this.allDLs.isGroup(addr);
/*  4568 */     if (!isDL) {
/*       */       try {
/*  4570 */         addr = getEmailAddrByDomainAlias(addr);
/*  4571 */         if (addr != null) {
/*  4572 */           isDL = this.allDLs.isGroup(addr);
/*       */         }
/*       */       } catch (ServiceException e) {
/*  4575 */         ZimbraLog.account.warn("unable to get local domain address of " + addr, e);
/*       */       }
/*       */     }
/*  4578 */     return isDL;
/*       */   }
/*       */   
/*       */   private Group getGroupFromCache(Key.DistributionListBy keyType, String key) {
/*  4582 */     switch (keyType) {
/*       */     case id: 
/*  4584 */       return (Group)this.groupCache.getById(key);
/*       */     case name: 
/*  4586 */       return (Group)this.groupCache.getByName(key);
/*       */     }
/*  4588 */     return null;
/*       */   }
/*       */   
/*       */   private void putInGroupCache(Group group)
/*       */   {
/*  4593 */     this.groupCache.put(group);
/*       */   }
/*       */   
/*       */   private DistributionList getDLFromCache(Key.DistributionListBy keyType, String key) {
/*  4597 */     Group group = getGroupFromCache(keyType, key);
/*  4598 */     if ((group instanceof DistributionList)) {
/*  4599 */       return (DistributionList)group;
/*       */     }
/*  4601 */     return null;
/*       */   }
/*       */   
/*       */   void removeGroupFromCache(Key.DistributionListBy keyType, String key)
/*       */   {
/*  4606 */     Group group = getGroupFromCache(keyType, key);
/*  4607 */     if (group != null) {
/*  4608 */       removeFromCache(group);
/*       */     }
/*       */   }
/*       */   
/*       */   private Provisioning.GroupMembership getAdminAclGroups(Provisioning.GroupMembership aclGroups)
/*       */   {
/*  4614 */     List<Provisioning.MemberOf> groups = new ArrayList();
/*  4615 */     List<String> groupIds = new ArrayList();
/*       */     
/*  4617 */     List<Provisioning.MemberOf> memberOf = aclGroups.memberOf();
/*  4618 */     for (Provisioning.MemberOf mo : memberOf) {
/*  4619 */       if (mo.isAdminGroup()) {
/*  4620 */         groups.add(mo);
/*  4621 */         groupIds.add(mo.getId());
/*       */       }
/*       */     }
/*       */     
/*  4625 */     groups = Collections.unmodifiableList(groups);
/*  4626 */     groupIds = Collections.unmodifiableList(groupIds);
/*       */     
/*  4628 */     return new Provisioning.GroupMembership(groups, groupIds);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   public Provisioning.GroupMembership getGroupMembership(Account acct, boolean adminGroupsOnly)
/*       */     throws ServiceException
/*       */   {
/*  4637 */     EntryCacheDataKey cacheKey = adminGroupsOnly ? EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP_ADMINS_ONLY : EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP;
/*       */     
/*       */ 
/*       */ 
/*  4641 */     Provisioning.GroupMembership cacheableGroups = (Provisioning.GroupMembership)acct.getCachedData(cacheKey);
/*  4642 */     if (cacheableGroups == null) {
/*  4643 */       cacheableGroups = setupGroupedEntryCacheData(acct, adminGroupsOnly);
/*       */     }
/*  4645 */     return cacheableGroups.clone();
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public Provisioning.GroupMembership getCustomDynamicGroupMembership(Account acct, boolean adminGroupsOnly)
/*       */     throws ServiceException
/*       */   {
/*  4653 */     Provisioning.GroupMembership groups = new Provisioning.GroupMembership();
/*  4654 */     return LdapDynamicGroup.updateGroupMembershipForCustomDynamicGroups(this, groups, acct, (Domain)null, adminGroupsOnly);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public Provisioning.GroupMembership getGroupMembershipWithRights(Account acct, Set<Right> rights, boolean adminGroupsOnly)
/*       */     throws ServiceException
/*       */   {
/*  4665 */     SearchForGroupsWithRightsVisitor visitor = new SearchForGroupsWithRightsVisitor(rights);
/*  4666 */     Set<String> groupsWithRights = searchForGroupsWhichUseRights(getDIT().zimbraBaseDN(), rights, visitor);
/*  4667 */     if (groupsWithRights.size() == 0) {
/*  4668 */       return new Provisioning.GroupMembership();
/*       */     }
/*  4670 */     Provisioning.GroupMembership membership = getGroupMembership(acct, adminGroupsOnly);
/*  4671 */     return restrictMembershipByIds(membership, groupsWithRights);
/*       */   }
/*       */   
/*       */   private Provisioning.GroupMembership restrictMembershipByIds(Provisioning.GroupMembership groups, Collection<String> ids) {
/*  4675 */     Provisioning.GroupMembership membership = new Provisioning.GroupMembership();
/*  4676 */     if (ids.size() == 0) {
/*  4677 */       return membership;
/*       */     }
/*  4679 */     for (Provisioning.MemberOf memberOf : groups.memberOf()) {
/*  4680 */       if (ids.contains(memberOf.getId())) {
/*  4681 */         membership.append(memberOf, memberOf.getId());
/*       */       }
/*       */     }
/*  4684 */     return membership;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   private static class SearchForGroupsWithRightsVisitor
/*       */     extends SearchLdapOptions.SearchLdapVisitor
/*       */   {
/*  4692 */     private final Set<String> results = Sets.newHashSet();
/*       */     private final Set<String> rightNames;
/*       */     
/*       */     SearchForGroupsWithRightsVisitor(Set<Right> rights) {
/*  4696 */       if ((rights == null) || (rights.isEmpty())) {
/*  4697 */         this.rightNames = null;
/*       */       } else {
/*  4699 */         this.rightNames = Sets.newHashSet();
/*  4700 */         for (Right right : rights) {
/*  4701 */           this.rightNames.add(right.getName());
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*       */     public void visit(String dn, Map<String, Object> attrs, IAttributes ldapAttrs)
/*       */     {
/*  4708 */       String[] zimbraACE = getMultiAttrString(attrs, "zimbraACE");
/*  4709 */       if (zimbraACE != null) {
/*  4710 */         for (String ace : zimbraACE)
/*       */         {
/*  4712 */           String[] components = ace.split(" ");
/*  4713 */           if (components.length >= 3)
/*       */           {
/*       */ 
/*  4716 */             if (("grp".equals(components[1])) && (
/*  4717 */               (this.rightNames == null) || (this.rightNames.contains(components[2])))) {
/*  4718 */               this.results.add(components[0]);
/*       */             }
/*       */           }
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*       */     private String[] getMultiAttrString(Map<String, Object> attrs, String attrName) {
/*  4726 */       Object obj = attrs.get(attrName);
/*  4727 */       if ((obj instanceof String)) {
/*  4728 */         return new String[] { (String)obj };
/*       */       }
/*  4730 */       return (String[])obj;
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private Set<String> searchForGroupsWhichUseRights(String base, Set<Right> rights, SearchForGroupsWithRightsVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  4744 */     String[] fetchAttrs = { "zimbraACE" };
/*  4745 */     StringBuilder query = new StringBuilder("(|");
/*  4746 */     if ((rights == null) || (rights.isEmpty())) {
/*  4747 */       query.append('(').append("zimbraACE").append('=').append("* grp *)");
/*       */     } else {
/*  4749 */       for (Right right : rights) {
/*  4750 */         query.append('(').append("zimbraACE").append('=').append("* grp ").append(right.getName()).append(")");
/*       */       }
/*       */     }
/*       */     
/*  4754 */     query.append(")");
/*       */     
/*  4756 */     searchLdapOnReplica(base, query.toString(), fetchAttrs, visitor);
/*  4757 */     return Collections.unmodifiableSet(visitor.results);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   private Provisioning.GroupMembership setupGroupedEntryCacheData(Account acct, boolean adminGroupsOnly)
/*       */     throws ServiceException
/*       */   {
/*  4765 */     Provisioning.GroupMembership groups = new Provisioning.GroupMembership();
/*  4766 */     DistributionList.updateGroupMembership(this, (ZLdapContext)null, groups, acct, null, false, false);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  4771 */     Set<String> allGroupIDs = getAllContainingDynamicGroupIDs(acct);
/*  4772 */     groups = LdapDynamicGroup.updateGroupMembershipForDynamicGroups(this, groups, acct, allGroupIDs, false, false, true);
/*       */     
/*       */ 
/*       */ 
/*  4776 */     Provisioning.GroupMembership customMembership = getCustomDynamicGroupMembership(acct, false);
/*  4777 */     groups.mergeFrom(customMembership);
/*       */     
/*       */ 
/*  4780 */     acct.setCachedData(EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP, groups);
/*       */     
/*       */ 
/*  4783 */     if (adminGroupsOnly) {
/*  4784 */       groups = getAdminAclGroups(groups);
/*  4785 */       acct.setCachedData(EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP_ADMINS_ONLY, groups);
/*       */     }
/*  4787 */     return groups;
/*       */   }
/*       */   
/*       */ 
/*       */   public Provisioning.GroupMembership getGroupMembership(DistributionList dl, boolean adminGroupsOnly)
/*       */     throws ServiceException
/*       */   {
/*  4794 */     EntryCacheDataKey cacheKey = adminGroupsOnly ? EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP_ADMINS_ONLY : EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP;
/*       */     
/*       */ 
/*       */ 
/*  4798 */     Provisioning.GroupMembership groups = (Provisioning.GroupMembership)dl.getCachedData(cacheKey);
/*  4799 */     if (groups != null) {
/*  4800 */       return groups;
/*       */     }
/*       */     
/*  4803 */     groups = new Provisioning.GroupMembership();
/*  4804 */     DistributionList.updateGroupMembership(this, (ZLdapContext)null, groups, dl, null, false, false);
/*       */     
/*       */ 
/*  4807 */     dl.setCachedData(EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP, groups);
/*       */     
/*  4809 */     if (adminGroupsOnly) {
/*  4810 */       groups = getAdminAclGroups(groups);
/*  4811 */       dl.setCachedData(EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP_ADMINS_ONLY, groups);
/*       */     }
/*       */     
/*  4814 */     return groups;
/*       */   }
/*       */   
/*       */   public Server getLocalServer() throws ServiceException
/*       */   {
/*  4819 */     String hostname = LC.zimbra_server_hostname.value();
/*  4820 */     if (hostname == null) {
/*  4821 */       Zimbra.halt("zimbra_server_hostname not specified in localconfig.xml");
/*       */     }
/*  4823 */     Server local = getServerByNameInternal(hostname);
/*  4824 */     if (local == null) {
/*  4825 */       Zimbra.halt("Could not find an LDAP entry for server '" + hostname + "'");
/*       */     }
/*  4827 */     return local;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private static final String DATA_GAL_RULES = "GAL_RULES";
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   private static final String IDENTITY_LIST_CACHE_KEY = "LdapProvisioning.IDENTITY_CACHE";
/*       */   
/*       */ 
/*       */ 
/*       */   private static final String SIGNATURE_LIST_CACHE_KEY = "LdapProvisioning.SIGNATURE_CACHE";
/*       */   
/*       */ 
/*       */ 
/*       */   private static final String DATA_SOURCE_LIST_CACHE_KEY = "LdapProvisioning.DATA_SOURCE_CACHE";
/*       */   
/*       */ 
/*       */ 
/*       */   private static final String DYNAMIC_GROUP_DYNAMIC_UNIT_NAME = "internal";
/*       */   
/*       */ 
/*       */ 
/*       */   private static final String DYNAMIC_GROUP_STATIC_UNIT_NAME = "external";
/*       */   
/*       */ 
/*       */ 
/*       */   private void checkAccountStatus(Account acct, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  4862 */     if (!onLocalServer(acct)) {
/*  4863 */       reload(acct, false);
/*       */     }
/*       */     
/*  4866 */     String accountStatus = acct.getAccountStatus(Provisioning.getInstance());
/*  4867 */     if (accountStatus == null) {
/*  4868 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), AuthMechanism.namePassedIn(authCtxt), "missing account status");
/*       */     }
/*       */     
/*       */ 
/*  4872 */     if (accountStatus.equals("maintenance")) {
/*  4873 */       throw AccountServiceException.MAINTENANCE_MODE();
/*       */     }
/*       */     
/*  4876 */     if ((!accountStatus.equals("active")) && (!accountStatus.equals("lockout")))
/*       */     {
/*  4878 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), AuthMechanism.namePassedIn(authCtxt), "account(or domain) status is " + accountStatus);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   public void preAuthAccount(Account acct, String acctValue, String acctBy, long timestamp, long expires, String preAuth, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  4888 */     preAuthAccount(acct, acctValue, acctBy, timestamp, expires, preAuth, false, authCtxt);
/*       */   }
/*       */   
/*       */ 
/*       */   public void preAuthAccount(Account acct, String acctValue, String acctBy, long timestamp, long expires, String preAuth, boolean admin, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*  4897 */       preAuth(acct, acctValue, acctBy, timestamp, expires, preAuth, admin, authCtxt);
/*  4898 */       ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] { "cmd", "PreAuth", "account", acct.getName(), "admin", admin + "" }));
/*       */     }
/*       */     catch (AccountServiceException.AuthFailedServiceException e) {
/*  4901 */       ZimbraLog.security.warn(ZimbraLog.encodeAttrs(new String[] { "cmd", "PreAuth", "account", acct.getName(), "admin", admin + "", "error", e.getMessage() + e.getReason(", %s") }));
/*       */       
/*  4903 */       throw e;
/*       */     } catch (ServiceException e) {
/*  4905 */       ZimbraLog.security.warn(ZimbraLog.encodeAttrs(new String[] { "cmd", "PreAuth", "account", acct.getName(), "admin", admin + "", "error", e.getMessage() }));
/*       */       
/*  4907 */       throw e;
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   public void preAuthAccount(Domain domain, String acctValue, String acctBy, long timestamp, long expires, String preAuth, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  4915 */     verifyPreAuth(domain, null, acctValue, acctBy, timestamp, expires, preAuth, false, authCtxt);
/*  4916 */     ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] { "cmd", "PreAuth", "account", acctValue }));
/*       */   }
/*       */   
/*       */   private void verifyPreAuth(Account acct, String acctValue, String acctBy, long timestamp, long expires, String preAuth, boolean admin, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  4922 */     checkAccountStatus(acct, authCtxt);
/*  4923 */     verifyPreAuth(Provisioning.getInstance().getDomain(acct), acct.getName(), acctValue, acctBy, timestamp, expires, preAuth, admin, authCtxt);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   void verifyPreAuth(Domain domain, String acctNameForLogging, String acctValue, String acctBy, long timestamp, long expires, String preAuth, boolean admin, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  4932 */     if ((preAuth == null) || (preAuth.length() == 0)) {
/*  4933 */       throw ServiceException.INVALID_REQUEST("preAuth must not be empty", null);
/*       */     }
/*  4935 */     if (acctNameForLogging == null) {
/*  4936 */       acctNameForLogging = acctValue;
/*       */     }
/*       */     
/*       */ 
/*  4940 */     String domainPreAuthKey = domain.getAttr("zimbraPreAuthKey", null);
/*  4941 */     if (domainPreAuthKey == null) {
/*  4942 */       throw ServiceException.INVALID_REQUEST("domain is not configured for preauth", null);
/*       */     }
/*       */     
/*  4945 */     long now = System.currentTimeMillis();
/*  4946 */     long diff = Math.abs(now - timestamp);
/*  4947 */     if (diff > 300000L) {
/*  4948 */       Date nowDate = new Date(now);
/*  4949 */       Date preauthDate = new Date(timestamp);
/*  4950 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acctNameForLogging, AuthMechanism.namePassedIn(authCtxt), "preauth timestamp is too old, server time: " + nowDate.toString() + ", preauth timestamp: " + preauthDate.toString());
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  4957 */     HashMap<String, String> params = new HashMap();
/*  4958 */     params.put("account", acctValue);
/*  4959 */     if (admin) params.put("admin", "1");
/*  4960 */     params.put("by", acctBy);
/*  4961 */     params.put("timestamp", timestamp + "");
/*  4962 */     params.put("expires", expires + "");
/*  4963 */     String computedPreAuth = PreAuthKey.computePreAuth(params, domainPreAuthKey);
/*  4964 */     if (!computedPreAuth.equalsIgnoreCase(preAuth)) {
/*  4965 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acctNameForLogging, AuthMechanism.namePassedIn(authCtxt), "preauth mismatch");
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   private void preAuth(Account acct, String acctValue, String acctBy, long timestamp, long expires, String preAuth, boolean admin, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  4974 */     LdapLockoutPolicy lockoutPolicy = new LdapLockoutPolicy(this, acct);
/*       */     try {
/*  4976 */       if (lockoutPolicy.isLockedOut()) {
/*  4977 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), AuthMechanism.namePassedIn(authCtxt), "account lockout");
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  4982 */       verifyPreAuth(acct, acctValue, acctBy, timestamp, expires, preAuth, admin, authCtxt);
/*       */       
/*  4984 */       lockoutPolicy.successfulLogin();
/*       */     } catch (AccountServiceException e) {
/*  4986 */       lockoutPolicy.failedLogin();
/*       */       
/*  4988 */       throw e;
/*       */     }
/*       */     
/*       */ 
/*  4992 */     updateLastLogon(acct);
/*       */   }
/*       */   
/*       */   public void authAccount(Account acct, String password, AuthContext.Protocol proto)
/*       */     throws ServiceException
/*       */   {
/*  4998 */     authAccount(acct, password, proto, null);
/*       */   }
/*       */   
/*       */   public void authAccount(Account acct, String password, AuthContext.Protocol proto, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*  5006 */       if ((password == null) || (password.equals(""))) {
/*  5007 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), AuthMechanism.namePassedIn(authCtxt), "empty password");
/*       */       }
/*       */       
/*       */ 
/*  5011 */       if (authCtxt == null) {
/*  5012 */         authCtxt = new HashMap();
/*       */       }
/*       */       
/*  5015 */       authCtxt.put("proto", proto);
/*       */       
/*  5017 */       authAccount(acct, password, true, authCtxt);
/*  5018 */       ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] { "cmd", "Auth", "account", acct.getName(), "protocol", proto.toString() }));
/*       */     }
/*       */     catch (AccountServiceException.AuthFailedServiceException e) {
/*  5021 */       ZimbraLog.security.warn(ZimbraLog.encodeAttrs(new String[] { "cmd", "Auth", "account", acct.getName(), "protocol", proto.toString(), "error", e.getMessage() + e.getReason(", %s") }));
/*       */       
/*  5023 */       throw e;
/*       */     } catch (ServiceException e) {
/*  5025 */       ZimbraLog.security.warn(ZimbraLog.encodeAttrs(new String[] { "cmd", "Auth", "account", acct.getName(), "protocol", proto.toString(), "error", e.getMessage() }));
/*       */       
/*  5027 */       throw e;
/*       */     }
/*       */   }
/*       */   
/*       */   private void authAccount(Account acct, String password, boolean checkPasswordPolicy, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  5034 */     checkAccountStatus(acct, authCtxt);
/*       */     
/*  5036 */     AuthMechanism authMech = AuthMechanism.newInstance(acct, authCtxt);
/*  5037 */     verifyPassword(acct, password, authMech, authCtxt);
/*       */     
/*       */ 
/*       */ 
/*  5041 */     if (!checkPasswordPolicy) {
/*  5042 */       return;
/*       */     }
/*  5044 */     if (authMech.checkPasswordAging())
/*       */     {
/*  5046 */       int maxAge = acct.getIntAttr("zimbraPasswordMaxAge", 0);
/*  5047 */       if (maxAge > 0) {
/*  5048 */         Date lastChange = acct.getGeneralizedTimeAttr("zimbraPasswordModifiedTime", null);
/*  5049 */         if (lastChange != null) {
/*  5050 */           long last = lastChange.getTime();
/*  5051 */           long curr = System.currentTimeMillis();
/*  5052 */           if (last + 86400000L * maxAge < curr) {
/*  5053 */             throw AccountServiceException.CHANGE_PASSWORD();
/*       */           }
/*       */         }
/*       */       }
/*  5057 */       boolean mustChange = acct.getBooleanAttr("zimbraPasswordMustChange", false);
/*  5058 */       if (mustChange) {
/*  5059 */         throw AccountServiceException.CHANGE_PASSWORD();
/*       */       }
/*       */     }
/*       */     
/*  5063 */     updateLastLogon(acct);
/*       */   }
/*       */   
/*       */   public void accountAuthed(Account acct)
/*       */     throws ServiceException
/*       */   {
/*  5069 */     updateLastLogon(acct);
/*       */   }
/*       */   
/*       */   public void ssoAuthAccount(Account acct, AuthContext.Protocol proto, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*  5077 */       ssoAuth(acct, authCtxt);
/*  5078 */       ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] { "cmd", "SSOAuth", "account", acct.getName(), "protocol", proto.toString() }));
/*       */     }
/*       */     catch (AccountServiceException.AuthFailedServiceException e) {
/*  5081 */       ZimbraLog.security.warn(ZimbraLog.encodeAttrs(new String[] { "cmd", "SSOAuth", "account", acct.getName(), "protocol", proto.toString(), "error", e.getMessage() + e.getReason(", %s") }));
/*       */       
/*  5083 */       throw e;
/*       */     } catch (ServiceException e) {
/*  5085 */       ZimbraLog.security.warn(ZimbraLog.encodeAttrs(new String[] { "cmd", "SSOAuth", "account", acct.getName(), "protocol", proto.toString(), "error", e.getMessage() }));
/*       */       
/*  5087 */       throw e;
/*       */     }
/*       */   }
/*       */   
/*       */   private void ssoAuth(Account acct, Map<String, Object> authCtxt) throws ServiceException
/*       */   {
/*  5093 */     checkAccountStatus(acct, authCtxt);
/*       */     
/*  5095 */     LdapLockoutPolicy lockoutPolicy = new LdapLockoutPolicy(this, acct);
/*       */     try {
/*  5097 */       if (lockoutPolicy.isLockedOut()) {
/*  5098 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), AuthMechanism.namePassedIn(authCtxt), "account lockout");
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  5103 */       lockoutPolicy.successfulLogin();
/*       */     } catch (AccountServiceException e) {
/*  5105 */       lockoutPolicy.failedLogin();
/*  5106 */       throw e;
/*       */     }
/*       */     
/*  5109 */     updateLastLogon(acct);
/*       */   }
/*       */   
/*       */   private void updateLastLogon(Account acct) throws ServiceException {
/*  5113 */     Config config = Provisioning.getInstance().getConfig();
/*  5114 */     long freq = config.getTimeInterval("zimbraLastLogonTimestampFrequency", 604800000L);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  5119 */     if (freq == 0L) {
/*  5120 */       return;
/*       */     }
/*  5122 */     Date lastLogon = acct.getGeneralizedTimeAttr("zimbraLastLogonTimestamp", null);
/*  5123 */     if (lastLogon == null) {
/*  5124 */       Map<String, String> attrs = new HashMap();
/*  5125 */       attrs.put("zimbraLastLogonTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*       */       try {
/*  5127 */         modifyAttrs(acct, attrs);
/*       */       } catch (ServiceException e) {
/*  5129 */         ZimbraLog.account.warn("updating zimbraLastLogonTimestamp", e);
/*       */       }
/*       */     } else {
/*  5132 */       long current = System.currentTimeMillis();
/*  5133 */       if (current - freq >= lastLogon.getTime()) {
/*  5134 */         Map<String, String> attrs = new HashMap();
/*  5135 */         attrs.put("zimbraLastLogonTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*       */         try {
/*  5137 */           modifyAttrs(acct, attrs);
/*       */         } catch (ServiceException e) {
/*  5139 */           ZimbraLog.account.warn("updating zimbraLastLogonTimestamp", e);
/*       */         }
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   private static Provisioning.Result toResult(ServiceException e, String dn) {
/*  5146 */     Throwable cause = e.getCause();
/*       */     
/*  5148 */     if ((cause instanceof IOException))
/*  5149 */       return Check.toResult((IOException)cause, dn);
/*  5150 */     if ((e instanceof LdapException)) {
/*  5151 */       LdapException ldapException = (LdapException)e;
/*  5152 */       Throwable detail = ldapException.getDetail();
/*  5153 */       if ((detail instanceof IOException))
/*  5154 */         return Check.toResult((IOException)detail, dn);
/*  5155 */       if (((ldapException instanceof LdapException.LdapEntryNotFoundException)) || ((detail instanceof LdapException.LdapEntryNotFoundException)))
/*       */       {
/*  5157 */         return new Provisioning.Result("check.NAME_NOT_FOUND", e, dn); }
/*  5158 */       if (((ldapException instanceof LdapException.LdapInvalidSearchFilterException)) || ((detail instanceof LdapException.LdapInvalidSearchFilterException)))
/*       */       {
/*  5160 */         return new Provisioning.Result("check.INVALID_SEARCH_FILTER", e, dn);
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*  5165 */     return new Provisioning.Result("check.AUTH_FAILED", e, dn);
/*       */   }
/*       */   
/*       */   private void ldapAuthenticate(String[] urls, boolean requireStartTLS, String principal, String password) throws ServiceException
/*       */   {
/*  5170 */     if ((password == null) || (password.equals(""))) {
/*  5171 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("empty password");
/*       */     }
/*       */     
/*  5174 */     LdapClient.externalLdapAuthenticate(urls, requireStartTLS, principal, password, "external LDAP auth");
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void ldapAuthenticate(String[] url, boolean wantStartTLS, String password, String searchBase, String searchFilter, String searchDn, String searchPassword)
/*       */     throws ServiceException
/*       */   {
/*  5184 */     if ((password == null) || (password.equals(""))) {
/*  5185 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("empty password");
/*       */     }
/*       */     
/*  5188 */     LdapServerConfig.ExternalLdapConfig config = new LdapServerConfig.ExternalLdapConfig(url, wantStartTLS, null, searchDn, searchPassword, null, "external LDAP auth");
/*       */     
/*       */ 
/*  5191 */     String resultDn = null;
/*  5192 */     String tooMany = null;
/*       */     
/*  5194 */     ZLdapContext zlc = null;
/*       */     try {
/*  5196 */       zlc = LdapClient.getExternalContext(config, LdapUsage.LDAP_AUTH_EXTERNAL);
/*  5197 */       ZSearchResultEnumeration ne = zlc.searchDir(searchBase, this.filterFactory.fromFilterString(ZLdapFilterFactory.FilterId.LDAP_AUTHENTICATE, searchFilter), ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*       */ 
/*       */ 
/*  5201 */       while (ne.hasMore()) {
/*  5202 */         ZSearchResultEntry sr = ne.next();
/*  5203 */         if (resultDn == null) {
/*  5204 */           resultDn = sr.getDN();
/*       */         } else {
/*  5206 */           tooMany = sr.getDN();
/*  5207 */           break;
/*       */         }
/*       */       }
/*  5210 */       ne.close();
/*       */     } finally {
/*  5212 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/*  5215 */     if (tooMany != null) {
/*  5216 */       ZimbraLog.account.warn(String.format("ldapAuthenticate searchFilter returned more then one result: (dn1=%s, dn2=%s, filter=%s)", new Object[] { resultDn, tooMany, searchFilter }));
/*       */       
/*       */ 
/*  5219 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("too many results from search filter!"); }
/*  5220 */     if (resultDn == null) {
/*  5221 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED("empty search");
/*       */     }
/*  5223 */     if (ZimbraLog.account.isDebugEnabled()) ZimbraLog.account.debug("search filter matched: " + resultDn);
/*  5224 */     ldapAuthenticate(url, wantStartTLS, resultDn, password);
/*       */   }
/*       */   
/*       */   public Provisioning.Result checkAuthConfig(Map attrs, String name, String password)
/*       */     throws ServiceException
/*       */   {
/*  5230 */     AuthMechanism.AuthMech mech = AuthMechanism.AuthMech.fromString(Check.getRequiredAttr(attrs, "zimbraAuthMech"));
/*  5231 */     if ((mech != AuthMechanism.AuthMech.ldap) && (mech != AuthMechanism.AuthMech.ad)) {
/*  5232 */       throw ServiceException.INVALID_REQUEST("auth mech must be: " + AuthMechanism.AuthMech.ldap.name() + " or " + AuthMechanism.AuthMech.ad.name(), null);
/*       */     }
/*       */     
/*       */ 
/*  5236 */     String[] url = Check.getRequiredMultiAttr(attrs, "zimbraAuthLdapURL");
/*       */     
/*       */ 
/*  5239 */     String startTLSEnabled = (String)attrs.get("zimbraAuthLdapStartTlsEnabled");
/*  5240 */     boolean requireStartTLS = startTLSEnabled == null ? false : "TRUE".equals(startTLSEnabled);
/*       */     try
/*       */     {
/*  5243 */       String searchFilter = (String)attrs.get("zimbraAuthLdapSearchFilter");
/*  5244 */       if (searchFilter != null) {
/*  5245 */         String searchPassword = (String)attrs.get("zimbraAuthLdapSearchBindPassword");
/*  5246 */         String searchDn = (String)attrs.get("zimbraAuthLdapSearchBindDn");
/*  5247 */         String searchBase = (String)attrs.get("zimbraAuthLdapSearchBase");
/*  5248 */         if (searchBase == null) searchBase = "";
/*  5249 */         searchFilter = LdapUtil.computeDn(name, searchFilter);
/*  5250 */         if (ZimbraLog.account.isDebugEnabled()) ZimbraLog.account.debug("auth with search filter of " + searchFilter);
/*  5251 */         ldapAuthenticate(url, requireStartTLS, password, searchBase, searchFilter, searchDn, searchPassword);
/*  5252 */         return new Provisioning.Result("check.OK", "", searchFilter);
/*       */       }
/*       */       
/*  5255 */       String bindDn = (String)attrs.get("zimbraAuthLdapBindDn");
/*  5256 */       if (bindDn != null) {
/*  5257 */         String dn = LdapUtil.computeDn(name, bindDn);
/*  5258 */         if (ZimbraLog.account.isDebugEnabled()) ZimbraLog.account.debug("auth with bind dn template of " + dn);
/*  5259 */         ldapAuthenticate(url, requireStartTLS, dn, password);
/*  5260 */         return new Provisioning.Result("check.OK", "", dn);
/*       */       }
/*       */       
/*  5263 */       throw ServiceException.INVALID_REQUEST("must specify zimbraAuthLdapSearchFilter or zimbraAuthLdapBindDn", null);
/*       */     }
/*       */     catch (ServiceException e) {
/*  5266 */       return toResult(e, "");
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   public Provisioning.Result checkGalConfig(Map attrs, String query, int limit, GalOp galOp)
/*       */     throws ServiceException
/*       */   {
/*  5274 */     Provisioning.GalMode mode = Provisioning.GalMode.fromString(Check.getRequiredAttr(attrs, "zimbraGalMode"));
/*  5275 */     if (mode != Provisioning.GalMode.ldap) {
/*  5276 */       throw ServiceException.INVALID_REQUEST("gal mode must be: " + Provisioning.GalMode.ldap.toString(), null);
/*       */     }
/*  5278 */     GalParams.ExternalGalParams galParams = new GalParams.ExternalGalParams(attrs, galOp);
/*       */     
/*  5280 */     LdapGalMapRules rules = new LdapGalMapRules(Provisioning.getInstance().getConfig(), false);
/*       */     try
/*       */     {
/*  5283 */       Provisioning.SearchGalResult result = null;
/*  5284 */       if (galOp == GalOp.autocomplete) {
/*  5285 */         result = LdapGalSearch.searchLdapGal(galParams, GalOp.autocomplete, query, limit, rules, null, null);
/*  5286 */       } else if (galOp == GalOp.search) {
/*  5287 */         result = LdapGalSearch.searchLdapGal(galParams, GalOp.search, query, limit, rules, null, null);
/*  5288 */       } else if (galOp == GalOp.sync) {
/*  5289 */         result = LdapGalSearch.searchLdapGal(galParams, GalOp.sync, query, limit, rules, "", null);
/*       */       } else {
/*  5291 */         throw ServiceException.INVALID_REQUEST("invalid GAL op: " + galOp.toString(), null);
/*       */       }
/*  5293 */       return new com.zimbra.cs.account.Provisioning.GalResult("check.OK", "", result.getMatches());
/*       */     } catch (ServiceException e) {
/*  5295 */       return toResult(e, "");
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   public void externalLdapAuth(Domain domain, AuthMechanism.AuthMech authMech, Account acct, String password, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  5303 */     externalLdapAuth(domain, authMech, acct, null, password, authCtxt);
/*       */   }
/*       */   
/*       */ 
/*       */   public void externalLdapAuth(Domain d, AuthMechanism.AuthMech authMech, String principal, String password, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  5310 */     externalLdapAuth(d, authMech, null, principal, password, authCtxt);
/*       */   }
/*       */   
/*       */ 
/*       */   void externalLdapAuth(Domain d, AuthMechanism.AuthMech authMech, Account acct, String principal, String password, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  5317 */     if (!$assertionsDisabled) if ((acct == null ? 1 : 0) == (principal == null ? 1 : 0)) { throw new AssertionError();
/*       */       }
/*  5319 */     String[] url = d.getMultiAttr("zimbraAuthLdapURL");
/*       */     
/*  5321 */     if ((url == null) || (url.length == 0)) {
/*  5322 */       String msg = "attr not set zimbraAuthLdapURL";
/*  5323 */       ZimbraLog.account.fatal(msg);
/*  5324 */       throw ServiceException.FAILURE(msg, null);
/*       */     }
/*       */     
/*  5327 */     boolean requireStartTLS = d.getBooleanAttr("zimbraAuthLdapStartTlsEnabled", false);
/*       */     
/*       */     try
/*       */     {
/*  5331 */       if (acct != null) {
/*  5332 */         String externalDn = acct.getAttr("zimbraAuthLdapExternalDn");
/*  5333 */         if (externalDn != null) {
/*  5334 */           ZimbraLog.account.debug("auth with explicit dn of " + externalDn);
/*  5335 */           ldapAuthenticate(url, requireStartTLS, externalDn, password);
/*  5336 */           return;
/*       */         }
/*       */         
/*       */ 
/*  5340 */         principal = acct.getName();
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  5345 */       String searchFilter = d.getAttr("zimbraAuthLdapSearchFilter");
/*  5346 */       if ((searchFilter != null) && (AuthMechanism.AuthMech.ad != authMech)) {
/*  5347 */         String searchPassword = d.getAttr("zimbraAuthLdapSearchBindPassword");
/*  5348 */         String searchDn = d.getAttr("zimbraAuthLdapSearchBindDn");
/*  5349 */         String searchBase = d.getAttr("zimbraAuthLdapSearchBase");
/*  5350 */         if (searchBase == null) {
/*  5351 */           searchBase = "";
/*       */         }
/*  5353 */         searchFilter = LdapUtil.computeDn(principal, searchFilter);
/*  5354 */         ZimbraLog.account.debug("auth with search filter of " + searchFilter);
/*  5355 */         ldapAuthenticate(url, requireStartTLS, password, searchBase, searchFilter, searchDn, searchPassword);
/*  5356 */         return;
/*       */       }
/*       */       
/*  5359 */       String bindDn = d.getAttr("zimbraAuthLdapBindDn");
/*  5360 */       if (bindDn != null) {
/*  5361 */         String dn = LdapUtil.computeDn(principal, bindDn);
/*  5362 */         ZimbraLog.account.debug("auth with bind dn template of " + dn);
/*  5363 */         ldapAuthenticate(url, requireStartTLS, dn, password);
/*  5364 */         return;
/*       */       }
/*       */     } catch (ServiceException e) {
/*  5367 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(principal, AuthMechanism.namePassedIn(authCtxt), "external LDAP auth failed, " + e.getMessage(), e);
/*       */     }
/*       */     
/*       */ 
/*  5371 */     String msg = "one of the following attrs must be set zimbraAuthLdapBindDn, zimbraAuthLdapSearchFilter";
/*       */     
/*  5373 */     ZimbraLog.account.fatal(msg);
/*  5374 */     throw ServiceException.FAILURE(msg, null);
/*       */   }
/*       */   
/*       */   public void zimbraLdapAuthenticate(Account acct, String password, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*  5382 */       LdapClient.zimbraLdapAuthenticate(((LdapEntry)acct).getDN(), password);
/*       */     } catch (ServiceException e) {
/*  5384 */       throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), AuthMechanism.namePassedIn(authCtxt), e.getMessage(), e);
/*       */     }
/*       */   }
/*       */   
/*       */   private boolean isProtocolEnabled(Account authAccount, AuthContext.Protocol protocol)
/*       */   {
/*  5390 */     if (protocol == null) {
/*  5391 */       return true;
/*       */     }
/*  5393 */     switch (protocol) {
/*       */     case imap: 
/*  5395 */       return authAccount.isImapEnabled();
/*       */     
/*       */     case pop3: 
/*  5398 */       return authAccount.isPop3Enabled();
/*       */     }
/*       */     
/*  5401 */     return true;
/*       */   }
/*       */   
/*       */ 
/*       */   private void verifyPassword(Account acct, String password, AuthMechanism authMech, Map<String, Object> authCtxt)
/*       */     throws ServiceException
/*       */   {
/*  5408 */     synchronized (acct) {
/*  5409 */       LdapLockoutPolicy lockoutPolicy = new LdapLockoutPolicy(this, acct);
/*  5410 */       if (lockoutPolicy.isLockedOut()) {
/*       */         try {
/*  5412 */           verifyPasswordInternal(acct, password, authMech, authCtxt);
/*       */         } catch (ServiceException e) {
/*  5414 */           lockoutPolicy.failedLogin();
/*       */         }
/*  5416 */         throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(acct.getName(), AuthMechanism.namePassedIn(authCtxt), "account lockout");
/*       */       }
/*       */       
/*       */       try
/*       */       {
/*  5421 */         verifyPasswordInternal(acct, password, authMech, authCtxt);
/*  5422 */         lockoutPolicy.successfulLogin();
/*       */       } catch (AccountServiceException e) {
/*  5424 */         AuthContext.Protocol protocol = null;
/*  5425 */         if (authCtxt != null) {
/*  5426 */           protocol = (AuthContext.Protocol)authCtxt.get("proto");
/*       */         }
/*  5428 */         if (!isProtocolEnabled(acct, protocol)) {
/*  5429 */           ZimbraLog.account.info("%s not enabled for %s", new Object[] { protocol, acct.getName() });
/*       */         } else {
/*  5431 */           String strProtocol = protocol != null ? protocol.toString() : null;
/*  5432 */           lockoutPolicy.failedLogin(strProtocol, password);
/*       */         }
/*       */         
/*  5435 */         throw e;
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void verifyPasswordInternal(Account acct, String password, AuthMechanism authMech, Map<String, Object> context)
/*       */     throws ServiceException
/*       */   {
/*  5448 */     Domain domain = Provisioning.getInstance().getDomain(acct);
/*       */     
/*  5450 */     boolean allowFallback = true;
/*  5451 */     if (!authMech.isZimbraAuth()) {
/*  5452 */       allowFallback = (domain.getBooleanAttr("zimbraAuthFallbackToLocal", false)) || (acct.getBooleanAttr("zimbraIsAdminAccount", false)) || (acct.getBooleanAttr("zimbraIsDomainAdminAccount", false));
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */     try
/*       */     {
/*  5459 */       authMech.doAuth(this, domain, acct, password, context);
/*  5460 */       AuthMechanism.AuthMech authedByMech = authMech.getMechanism();
/*       */       
/*       */ 
/*  5463 */       return;
/*       */     } catch (ServiceException e) {
/*  5465 */       if ((!allowFallback) || (authMech.isZimbraAuth()))
/*  5466 */         throw e;
/*  5467 */       ZimbraLog.account.warn(authMech.getMechanism() + " auth for domain " + domain.getName() + " failed, fall back to zimbra default auth mechanism", e);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  5472 */       AuthMechanism.doZimbraAuth(this, domain, acct, password, context);
/*       */     }
/*       */   }
/*       */   
/*       */   public void changePassword(Account acct, String currentPassword, String newPassword)
/*       */     throws ServiceException
/*       */   {
/*  5479 */     authAccount(acct, currentPassword, false, null);
/*  5480 */     boolean locked = acct.getBooleanAttr("zimbraPasswordLocked", false);
/*  5481 */     if (locked)
/*  5482 */       throw AccountServiceException.PASSWORD_LOCKED();
/*  5483 */     setPassword(acct, newPassword, true, false);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   private void checkHistory(String newPassword, String[] history)
/*       */     throws AccountServiceException
/*       */   {
/*  5492 */     if (history == null)
/*  5493 */       return;
/*  5494 */     for (int i = 0; i < history.length; i++) {
/*  5495 */       int sepIndex = history[i].indexOf(':');
/*  5496 */       if (sepIndex != -1) {
/*  5497 */         String encoded = history[i].substring(sepIndex + 1);
/*  5498 */         if (PasswordUtil.SSHA.isSSHA(encoded)) {
/*  5499 */           if (PasswordUtil.SSHA.verifySSHA(encoded, newPassword))
/*  5500 */             throw AccountServiceException.PASSWORD_RECENTLY_USED();
/*  5501 */         } else if (PasswordUtil.SSHA512.isSSHA512(encoded)) {
/*  5502 */           if (PasswordUtil.SSHA512.verifySSHA512(encoded, newPassword))
/*  5503 */             throw AccountServiceException.PASSWORD_RECENTLY_USED();
/*       */         } else {
/*  5505 */           ZimbraLog.account.debug("password hash neither SSHA nor SSHA512; ignored for password history");
/*       */         }
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private String[] updateHistory(String[] history, String currentPassword, int maxHistory)
/*       */   {
/*  5520 */     if (currentPassword == null) {
/*  5521 */       return null;
/*       */     }
/*  5523 */     ArrayList<String> newHistory = new ArrayList();
/*  5524 */     String currentHistory = System.currentTimeMillis() + ":" + currentPassword;
/*  5525 */     if (history != null) {
/*  5526 */       newHistory.addAll(Arrays.asList(history));
/*  5527 */       Collections.sort(newHistory);
/*       */     }
/*  5529 */     while (newHistory.size() >= maxHistory) {
/*  5530 */       newHistory.remove(0);
/*       */     }
/*  5532 */     newHistory.add(currentHistory);
/*       */     
/*  5534 */     return (String[])newHistory.toArray(new String[newHistory.size()]);
/*       */   }
/*       */   
/*       */   public Provisioning.SetPasswordResult setPassword(Account acct, String newPassword)
/*       */     throws ServiceException
/*       */   {
/*  5540 */     return setPassword(acct, newPassword, false);
/*       */   }
/*       */   
/*       */ 
/*       */   public Provisioning.SetPasswordResult setPassword(Account acct, String newPassword, boolean enforcePasswordPolicy)
/*       */     throws ServiceException
/*       */   {
/*  5547 */     Provisioning.SetPasswordResult result = new Provisioning.SetPasswordResult();
/*  5548 */     String msg = null;
/*       */     
/*       */     try
/*       */     {
/*  5552 */       setPassword(acct, newPassword, false, true);
/*       */     } catch (ServiceException e) {
/*  5554 */       msg = e.getMessage();
/*       */     }
/*       */     
/*  5557 */     setPassword(acct, newPassword, enforcePasswordPolicy, false);
/*       */     
/*  5559 */     if (msg != null) {
/*  5560 */       msg = com.zimbra.common.util.L10nUtil.getMessage(com.zimbra.common.util.L10nUtil.MsgKey.passwordViolation, acct.getLocale(), new Object[] { acct.getName(), msg });
/*       */       
/*       */ 
/*  5563 */       result.setMessage(msg);
/*       */     }
/*       */     
/*  5566 */     return result;
/*       */   }
/*       */   
/*       */   public void checkPasswordStrength(Account acct, String password)
/*       */     throws ServiceException
/*       */   {
/*  5572 */     checkPasswordStrength(password, acct, null, null);
/*       */   }
/*       */   
/*       */   private int getInt(Account acct, Cos cos, ZMutableEntry entry, String name, int defaultValue) throws ServiceException
/*       */   {
/*  5577 */     if (acct != null) {
/*  5578 */       return acct.getIntAttr(name, defaultValue);
/*       */     }
/*       */     try
/*       */     {
/*  5582 */       String v = entry.getAttrString(name);
/*  5583 */       if (v != null) {
/*       */         try {
/*  5585 */           return Integer.parseInt(v);
/*       */         } catch (NumberFormatException e) {
/*  5587 */           return defaultValue;
/*       */         }
/*       */       }
/*       */     } catch (ServiceException ne) {
/*  5591 */       throw ServiceException.FAILURE(ne.getMessage(), ne);
/*       */     }
/*       */     
/*  5594 */     return cos.getIntAttr(name, defaultValue);
/*       */   }
/*       */   
/*       */   private String getString(Account acct, Cos cos, ZMutableEntry entry, String name) throws ServiceException
/*       */   {
/*  5599 */     if (acct != null) {
/*  5600 */       return acct.getAttr(name);
/*       */     }
/*       */     try
/*       */     {
/*  5604 */       String v = entry.getAttrString(name);
/*  5605 */       if (v != null) {
/*  5606 */         return v;
/*       */       }
/*       */     } catch (ServiceException ne) {
/*  5609 */       throw ServiceException.FAILURE(ne.getMessage(), ne);
/*       */     }
/*       */     
/*  5612 */     return cos.getAttr(name);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void checkPasswordStrength(String password, Account acct, Cos cos, ZMutableEntry entry)
/*       */     throws ServiceException
/*       */   {
/*  5627 */     int minLength = getInt(acct, cos, entry, "zimbraPasswordMinLength", 0);
/*  5628 */     if ((minLength > 0) && (password.length() < minLength)) {
/*  5629 */       throw AccountServiceException.INVALID_PASSWORD("too short", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMinLength", minLength, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */     
/*       */ 
/*  5633 */     int maxLength = getInt(acct, cos, entry, "zimbraPasswordMaxLength", 0);
/*  5634 */     if ((maxLength > 0) && (password.length() > maxLength)) {
/*  5635 */       throw AccountServiceException.INVALID_PASSWORD("too long", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMaxLength", maxLength, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */     
/*       */ 
/*  5639 */     int minUpperCase = getInt(acct, cos, entry, "zimbraPasswordMinUpperCaseChars", 0);
/*  5640 */     int minLowerCase = getInt(acct, cos, entry, "zimbraPasswordMinLowerCaseChars", 0);
/*  5641 */     int minNumeric = getInt(acct, cos, entry, "zimbraPasswordMinNumericChars", 0);
/*  5642 */     int minPunctuation = getInt(acct, cos, entry, "zimbraPasswordMinPunctuationChars", 0);
/*  5643 */     int minAlpha = getInt(acct, cos, entry, "zimbraPasswordMinAlphaChars", 0);
/*  5644 */     int minNumOrPunc = getInt(acct, cos, entry, "zimbraPasswordMinDigitsOrPuncs", 0);
/*       */     
/*  5646 */     String allowedChars = getString(acct, cos, entry, "zimbraPasswordAllowedChars");
/*  5647 */     Pattern allowedCharsPattern = null;
/*  5648 */     if (allowedChars != null) {
/*       */       try {
/*  5650 */         allowedCharsPattern = Pattern.compile(allowedChars);
/*       */       } catch (PatternSyntaxException e) {
/*  5652 */         throw AccountServiceException.INVALID_PASSWORD("zimbraPasswordAllowedChars is not valid regex: " + e.getMessage());
/*       */       }
/*       */     }
/*       */     
/*  5656 */     String allowedPuncChars = getString(acct, cos, entry, "zimbraPasswordAllowedPunctuationChars");
/*  5657 */     Pattern allowedPuncCharsPattern = null;
/*  5658 */     if (allowedPuncChars != null) {
/*       */       try {
/*  5660 */         allowedPuncCharsPattern = Pattern.compile(allowedPuncChars);
/*       */       } catch (PatternSyntaxException e) {
/*  5662 */         throw AccountServiceException.INVALID_PASSWORD("zimbraPasswordAllowedPunctuationChars is not valid regex: " + e.getMessage());
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*  5667 */     boolean hasPolicies = (minUpperCase > 0) || (minLowerCase > 0) || (minNumeric > 0) || (minPunctuation > 0) || (minAlpha > 0) || (minNumOrPunc > 0) || (allowedCharsPattern != null) || (allowedPuncCharsPattern != null);
/*       */     
/*       */ 
/*  5670 */     if (!hasPolicies) {
/*  5671 */       return;
/*       */     }
/*       */     
/*  5674 */     int upper = 0;
/*  5675 */     int lower = 0;
/*  5676 */     int numeric = 0;
/*  5677 */     int punctuation = 0;
/*  5678 */     int alpha = 0;
/*       */     
/*  5680 */     for (int i = 0; i < password.length(); i++) {
/*  5681 */       char ch = password.charAt(i);
/*       */       
/*  5683 */       if ((allowedCharsPattern != null) && 
/*  5684 */         (!allowedCharsPattern.matcher(Character.toString(ch)).matches())) {
/*  5685 */         throw AccountServiceException.INVALID_PASSWORD(ch + " is not an allowed character", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordAllowedChars", allowedChars, ServiceException.Argument.Type.STR) });
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  5690 */       boolean isAlpha = true;
/*  5691 */       if (Character.isUpperCase(ch)) {
/*  5692 */         upper++;
/*  5693 */       } else if (Character.isLowerCase(ch)) {
/*  5694 */         lower++;
/*  5695 */       } else if (Character.isDigit(ch)) {
/*  5696 */         numeric++;
/*  5697 */         isAlpha = false;
/*  5698 */       } else if (allowedPuncCharsPattern != null) {
/*  5699 */         if (allowedPuncCharsPattern.matcher(Character.toString(ch)).matches()) {
/*  5700 */           punctuation++;
/*  5701 */           isAlpha = false;
/*       */         }
/*  5703 */       } else if (isAsciiPunc(ch)) {
/*  5704 */         punctuation++;
/*  5705 */         isAlpha = false;
/*       */       }
/*  5707 */       if (isAlpha) {
/*  5708 */         alpha++;
/*       */       }
/*       */     }
/*       */     
/*  5712 */     if (upper < minUpperCase) {
/*  5713 */       throw AccountServiceException.INVALID_PASSWORD("not enough upper case characters", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMinUpperCaseChars", minUpperCase, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */     
/*  5716 */     if (lower < minLowerCase) {
/*  5717 */       throw AccountServiceException.INVALID_PASSWORD("not enough lower case characters", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMinLowerCaseChars", minLowerCase, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */     
/*  5720 */     if (numeric < minNumeric) {
/*  5721 */       throw AccountServiceException.INVALID_PASSWORD("not enough numeric characters", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMinNumericChars", minNumeric, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */     
/*  5724 */     if (punctuation < minPunctuation) {
/*  5725 */       throw AccountServiceException.INVALID_PASSWORD("not enough punctuation characters", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMinPunctuationChars", minPunctuation, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */     
/*  5728 */     if (alpha < minAlpha) {
/*  5729 */       throw AccountServiceException.INVALID_PASSWORD("not enough alpha characters", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMinAlphaChars", minAlpha, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */     
/*  5732 */     if (numeric + punctuation < minNumOrPunc) {
/*  5733 */       throw AccountServiceException.INVALID_PASSWORD("not enough numeric or punctuation characters", new ServiceException.Argument[] { new ServiceException.Argument("zimbraPasswordMinDigitsOrPuncs", minNumOrPunc, ServiceException.Argument.Type.NUM) });
/*       */     }
/*       */   }
/*       */   
/*       */   private boolean isAsciiPunc(char ch)
/*       */   {
/*  5739 */     return ((ch >= '!') && (ch <= '/')) || ((ch >= ':') && (ch <= '@')) || ((ch >= '[') && (ch <= '`')) || ((ch >= '{') && (ch <= '~'));
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   void setPassword(Account acct, String newPassword, boolean enforcePolicy, boolean dryRun)
/*       */     throws ServiceException
/*       */   {
/*  5749 */     boolean mustChange = acct.getBooleanAttr("zimbraPasswordMustChange", false);
/*       */     
/*  5751 */     if ((enforcePolicy) || (dryRun)) {
/*  5752 */       checkPasswordStrength(newPassword, acct, null, null);
/*       */       
/*       */ 
/*  5755 */       if (!mustChange) {
/*  5756 */         int minAge = acct.getIntAttr("zimbraPasswordMinAge", 0);
/*  5757 */         if (minAge > 0) {
/*  5758 */           Date lastChange = acct.getGeneralizedTimeAttr("zimbraPasswordModifiedTime", null);
/*  5759 */           if (lastChange != null) {
/*  5760 */             long last = lastChange.getTime();
/*  5761 */             long curr = System.currentTimeMillis();
/*  5762 */             if (last + 86400000L * minAge > curr) {
/*  5763 */               throw AccountServiceException.PASSWORD_CHANGE_TOO_SOON();
/*       */             }
/*       */           }
/*       */         }
/*       */       }
/*       */     }
/*  5769 */     Map<String, Object> attrs = new HashMap();
/*       */     
/*  5771 */     int enforceHistory = acct.getIntAttr("zimbraPasswordEnforceHistory", 0);
/*  5772 */     if (enforceHistory > 0) {
/*  5773 */       String[] newHistory = updateHistory(acct.getMultiAttr("zimbraPasswordHistory"), acct.getAttr("userPassword"), enforceHistory);
/*       */       
/*       */ 
/*       */ 
/*  5777 */       attrs.put("zimbraPasswordHistory", newHistory);
/*       */       
/*  5779 */       if ((enforcePolicy) || (dryRun)) {
/*  5780 */         checkHistory(newPassword, newHistory);
/*       */       }
/*       */     }
/*  5783 */     if (dryRun) {
/*  5784 */       return;
/*       */     }
/*       */     
/*       */ 
/*  5788 */     if (mustChange) {
/*  5789 */       attrs.put("zimbraPasswordMustChange", "");
/*       */     }
/*  5791 */     attrs.put("zimbraPasswordModifiedTime", DateUtil.toGeneralizedTime(new Date()));
/*       */     
/*       */ 
/*  5794 */     int tokenValidityValue = acct.getAuthTokenValidityValue();
/*  5795 */     acct.setAuthTokenValidityValue(tokenValidityValue == Integer.MAX_VALUE ? 0 : tokenValidityValue + 1, attrs);
/*       */     
/*  5797 */     ChangePasswordListener.ChangePasswordListenerContext ctxts = new ChangePasswordListener.ChangePasswordListenerContext();
/*  5798 */     ChangePasswordListener.invokePreModify(acct, newPassword, ctxts, attrs);
/*       */     try
/*       */     {
/*  5801 */       setLdapPassword(acct, null, newPassword);
/*       */       
/*  5803 */       modifyAttrs(acct, attrs);
/*       */     } catch (ServiceException se) {
/*  5805 */       ChangePasswordListener.invokeOnException(acct, newPassword, ctxts, se);
/*  5806 */       throw se;
/*       */     }
/*       */     
/*  5809 */     ChangePasswordListener.invokePostModify(acct, newPassword, ctxts);
/*       */   }
/*       */   
/*       */   public Zimlet getZimlet(String name) throws ServiceException
/*       */   {
/*  5814 */     return getZimlet(name, null, true);
/*       */   }
/*       */   
/*       */   private Zimlet getFromCache(Key.ZimletBy keyType, String key) {
/*  5818 */     switch (keyType) {
/*       */     case name: 
/*  5820 */       return (Zimlet)this.zimletCache.getByName(key);
/*       */     case id: 
/*  5822 */       return (Zimlet)this.zimletCache.getById(key);
/*       */     }
/*  5824 */     return null;
/*       */   }
/*       */   
/*       */   Zimlet lookupZimlet(String name, ZLdapContext zlc) throws ServiceException
/*       */   {
/*  5829 */     return getZimlet(name, zlc, false);
/*       */   }
/*       */   
/*       */   private Zimlet getZimlet(String name, ZLdapContext initZlc, boolean useZimletCache)
/*       */     throws ServiceException
/*       */   {
/*  5835 */     LdapZimlet zimlet = null;
/*  5836 */     if (useZimletCache) {
/*  5837 */       zimlet = (LdapZimlet)this.zimletCache.getByName(name);
/*       */     }
/*       */     
/*  5840 */     if (zimlet != null) {
/*  5841 */       return zimlet;
/*       */     }
/*       */     try
/*       */     {
/*  5845 */       String dn = this.mDIT.zimletNameToDN(name);
/*  5846 */       ZAttributes attrs = this.helper.getAttributes(initZlc, LdapServerType.REPLICA, LdapUsage.GET_ZIMLET, dn, null);
/*       */       
/*  5848 */       zimlet = new LdapZimlet(dn, attrs, this);
/*  5849 */       if (useZimletCache) {
/*  5850 */         com.zimbra.cs.zimlet.ZimletUtil.reloadZimlet(name);
/*  5851 */         this.zimletCache.put(zimlet);
/*       */       }
/*  5853 */       return zimlet;
/*       */     } catch (LdapException.LdapEntryNotFoundException e) {
/*  5855 */       return null;
/*       */     } catch (ServiceException ne) {
/*  5857 */       throw ServiceException.FAILURE("unable to get zimlet: " + name, ne);
/*       */     } catch (ZimletException ze) {
/*  5859 */       throw ServiceException.FAILURE("unable to load zimlet: " + name, ze);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<Zimlet> listAllZimlets() throws ServiceException
/*       */   {
/*  5865 */     List<Zimlet> result = new ArrayList();
/*       */     try
/*       */     {
/*  5868 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.zimletBaseDN(), this.filterFactory.allZimlets(), ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/*  5870 */       while (ne.hasMore()) {
/*  5871 */         ZSearchResultEntry sr = ne.next();
/*  5872 */         result.add(new LdapZimlet(sr.getDN(), sr.getAttributes(), this));
/*       */       }
/*  5874 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  5876 */       throw ServiceException.FAILURE("unable to list all zimlets", e);
/*       */     }
/*       */     
/*  5879 */     Collections.sort(result);
/*  5880 */     return result;
/*       */   }
/*       */   
/*       */   public Zimlet createZimlet(String name, Map<String, Object> zimletAttrs)
/*       */     throws ServiceException
/*       */   {
/*  5886 */     name = name.toLowerCase().trim();
/*       */     
/*  5888 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  5889 */     AttributeManager.getInstance().preModify(zimletAttrs, null, callbackContext, true);
/*       */     
/*  5891 */     ZLdapContext zlc = null;
/*       */     try {
/*  5893 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_ZIMLET);
/*       */       
/*  5895 */       String hasKeyword = "FALSE";
/*  5896 */       if (zimletAttrs.containsKey("zimbraZimletKeyword")) {
/*  5897 */         hasKeyword = "TRUE";
/*       */       }
/*       */       
/*  5900 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  5901 */       entry.mapToAttrs(zimletAttrs);
/*       */       
/*  5903 */       entry.setAttr("objectClass", "zimbraZimletEntry");
/*  5904 */       entry.setAttr("zimbraZimletEnabled", "FALSE");
/*  5905 */       entry.setAttr("zimbraZimletIndexingEnabled", hasKeyword);
/*  5906 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*       */       
/*  5908 */       String dn = this.mDIT.zimletNameToDN(name);
/*  5909 */       entry.setDN(dn);
/*  5910 */       zlc.createEntry(entry);
/*       */       
/*  5912 */       Zimlet zimlet = lookupZimlet(name, zlc);
/*  5913 */       AttributeManager.getInstance().postModify(zimletAttrs, zimlet, callbackContext);
/*  5914 */       return zimlet;
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  5916 */       throw AccountServiceException.ZIMLET_EXISTS(name);
/*       */     } catch (LdapException e) {
/*  5918 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  5920 */       throw e;
/*       */     } catch (ServiceException e) {
/*  5922 */       throw ServiceException.FAILURE("unable to create zimlet: " + name, e);
/*       */     } finally {
/*  5924 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteZimlet(String name) throws ServiceException
/*       */   {
/*  5930 */     ZLdapContext zlc = null;
/*       */     try {
/*  5932 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_ZIMLET);
/*  5933 */       LdapZimlet zimlet = (LdapZimlet)getZimlet(name, zlc, true);
/*  5934 */       if (zimlet != null) {
/*  5935 */         this.zimletCache.remove(zimlet);
/*  5936 */         zlc.deleteEntry(zimlet.getDN());
/*       */       }
/*       */     } catch (ServiceException e) {
/*  5939 */       throw ServiceException.FAILURE("unable to delete zimlet: " + name, e);
/*       */     } finally {
/*  5941 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   public CalendarResource createCalendarResource(String emailAddress, String password, Map<String, Object> calResAttrs)
/*       */     throws ServiceException
/*       */   {
/*  5949 */     emailAddress = emailAddress.toLowerCase().trim();
/*       */     
/*  5951 */     calResAttrs.put("zimbraAccountCalendarUserType", ZAttrProvisioning.AccountCalendarUserType.RESOURCE.toString());
/*       */     
/*       */ 
/*  5954 */     SpecialAttrs specialAttrs = this.mDIT.handleSpecialAttrs(calResAttrs);
/*       */     
/*  5956 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*       */     
/*  5958 */     Set<String> ocs = LdapObjectClass.getCalendarResourceObjectClasses(this);
/*  5959 */     Account acct = createAccount(emailAddress, password, calResAttrs, specialAttrs, (String[])ocs.toArray(new String[0]), false, null);
/*       */     
/*       */ 
/*  5962 */     LdapCalendarResource resource = (LdapCalendarResource)getCalendarResourceById(acct.getId(), true);
/*       */     
/*  5964 */     AttributeManager.getInstance().postModify(calResAttrs, resource, callbackContext);
/*       */     
/*  5966 */     return resource;
/*       */   }
/*       */   
/*       */   public void deleteCalendarResource(String zimbraId)
/*       */     throws ServiceException
/*       */   {
/*  5972 */     deleteAccount(zimbraId);
/*       */   }
/*       */   
/*       */   public void renameCalendarResource(String zimbraId, String newName)
/*       */     throws ServiceException
/*       */   {
/*  5978 */     renameAccount(zimbraId, newName);
/*       */   }
/*       */   
/*       */   public CalendarResource get(Key.CalendarResourceBy keyType, String key)
/*       */     throws ServiceException
/*       */   {
/*  5984 */     return get(keyType, key, false);
/*       */   }
/*       */   
/*       */   public CalendarResource get(Key.CalendarResourceBy keyType, String key, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*  5990 */     switch (keyType) {
/*       */     case id: 
/*  5992 */       return getCalendarResourceById(key, loadFromMaster);
/*       */     case foreignPrincipal: 
/*  5994 */       return getCalendarResourceByForeignPrincipal(key, loadFromMaster);
/*       */     case name: 
/*  5996 */       return getCalendarResourceByName(key, loadFromMaster);
/*       */     }
/*  5998 */     return null;
/*       */   }
/*       */   
/*       */   private CalendarResource getCalendarResourceById(String zimbraId, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*  6004 */     if (zimbraId == null)
/*  6005 */       return null;
/*  6006 */     Account acct = this.accountCache.getById(zimbraId);
/*  6007 */     if (acct != null) {
/*  6008 */       if ((acct instanceof LdapCalendarResource)) {
/*  6009 */         return (LdapCalendarResource)acct;
/*       */       }
/*       */       
/*  6012 */       return null;
/*       */     }
/*       */     
/*  6015 */     LdapCalendarResource resource = (LdapCalendarResource)getAccountByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.calendarResourceById(zimbraId), null, loadFromMaster);
/*       */     
/*       */ 
/*       */ 
/*  6019 */     this.accountCache.put(resource);
/*  6020 */     return resource;
/*       */   }
/*       */   
/*       */   private CalendarResource getCalendarResourceByName(String emailAddress, boolean loadFromMaster) throws ServiceException
/*       */   {
/*  6025 */     emailAddress = fixupAccountName(emailAddress);
/*  6026 */     Account acct = this.accountCache.getByName(emailAddress);
/*  6027 */     if (acct != null) {
/*  6028 */       if ((acct instanceof LdapCalendarResource)) {
/*  6029 */         return (LdapCalendarResource)acct;
/*       */       }
/*       */       
/*  6032 */       return null;
/*       */     }
/*       */     
/*  6035 */     LdapCalendarResource resource = (LdapCalendarResource)getAccountByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.calendarResourceByName(emailAddress), null, loadFromMaster);
/*       */     
/*       */ 
/*       */ 
/*  6039 */     this.accountCache.put(resource);
/*  6040 */     return resource;
/*       */   }
/*       */   
/*       */   private CalendarResource getCalendarResourceByForeignPrincipal(String foreignPrincipal, boolean loadFromMaster) throws ServiceException
/*       */   {
/*  6045 */     LdapCalendarResource resource = (LdapCalendarResource)getAccountByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.calendarResourceByForeignPrincipal(foreignPrincipal), null, loadFromMaster);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  6050 */     this.accountCache.put(resource);
/*  6051 */     return resource;
/*       */   }
/*       */   
/*       */   private Account makeAccount(String dn, ZAttributes attrs) throws ServiceException {
/*  6055 */     return makeAccount(dn, attrs, null);
/*       */   }
/*       */   
/*       */   private Account makeAccountNoDefaults(String dn, ZAttributes attrs) throws ServiceException {
/*  6059 */     return makeAccount(dn, attrs, SearchDirectoryOptions.MakeObjectOpt.NO_DEFAULTS);
/*       */   }
/*       */   
/*       */   private Account makeAccount(String dn, ZAttributes attrs, SearchDirectoryOptions.MakeObjectOpt makeObjOpt) throws ServiceException
/*       */   {
/*  6064 */     String userType = attrs.getAttrString("zimbraAccountCalendarUserType");
/*  6065 */     boolean isAccount = (userType == null) || (userType.equals(ZAttrProvisioning.AccountCalendarUserType.USER.toString()));
/*       */     
/*  6067 */     String emailAddress = attrs.getAttrString("zimbraMailDeliveryAddress");
/*  6068 */     if (emailAddress == null) {
/*  6069 */       emailAddress = this.mDIT.dnToEmail(dn, attrs);
/*       */     }
/*  6071 */     Account acct = isAccount ? new LdapAccount(dn, emailAddress, attrs, null, this) : new LdapCalendarResource(dn, emailAddress, attrs, null, this);
/*       */     
/*       */ 
/*  6074 */     setAccountDefaults(acct, makeObjOpt);
/*       */     
/*  6076 */     return acct;
/*       */   }
/*       */   
/*       */   private void setAccountDefaults(Account acct, SearchDirectoryOptions.MakeObjectOpt makeObjOpt) throws ServiceException
/*       */   {
/*  6081 */     if (makeObjOpt != SearchDirectoryOptions.MakeObjectOpt.NO_DEFAULTS)
/*       */     {
/*  6083 */       if (makeObjOpt == SearchDirectoryOptions.MakeObjectOpt.NO_SECONDARY_DEFAULTS) {
/*  6084 */         acct.setAccountDefaults(false);
/*       */       } else
/*  6086 */         acct.setAccountDefaults(true);
/*       */     }
/*       */   }
/*       */   
/*       */   private Alias makeAlias(String dn, ZAttributes attrs) throws ServiceException {
/*  6091 */     String emailAddress = this.mDIT.dnToEmail(dn, attrs);
/*  6092 */     Alias alias = new com.zimbra.cs.account.ldap.entry.LdapAlias(dn, emailAddress, attrs, this);
/*  6093 */     return alias;
/*       */   }
/*       */   
/*       */   private DistributionList makeDistributionList(String dn, ZAttributes attrs, boolean isBasic) throws ServiceException
/*       */   {
/*  6098 */     String emailAddress = this.mDIT.dnToEmail(dn, attrs);
/*  6099 */     DistributionList dl = new LdapDistributionList(dn, emailAddress, attrs, isBasic, this);
/*  6100 */     return dl;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   private DynamicGroup makeDynamicGroup(ZLdapContext initZlc, String dn, ZAttributes attrs)
/*       */     throws ServiceException
/*       */   {
/*  6109 */     String emailAddress = this.mDIT.dnToEmail(dn, this.mDIT.dynamicGroupNamingRdnAttr(), attrs);
/*       */     
/*  6111 */     LdapDynamicGroup group = new LdapDynamicGroup(dn, emailAddress, attrs, this);
/*       */     
/*  6113 */     if (!group.isMembershipDefinedByCustomURL())
/*       */     {
/*  6115 */       String dynamicUnitDN = this.mDIT.dynamicGroupUnitNameToDN("internal", dn);
/*  6116 */       ZAttributes dynamicUnitAttrs = this.helper.getAttributes(initZlc, LdapServerType.REPLICA, LdapUsage.GET_GROUP_UNIT, dynamicUnitDN, null);
/*       */       
/*       */ 
/*  6119 */       LdapDynamicGroup.DynamicUnit dynamicUnit = new LdapDynamicGroup.DynamicUnit(dynamicUnitDN, "internal", dynamicUnitAttrs, this);
/*       */       
/*       */ 
/*       */ 
/*  6123 */       String staticUnitDN = this.mDIT.dynamicGroupUnitNameToDN("external", dn);
/*  6124 */       ZAttributes staticUnitAttrs = this.helper.getAttributes(initZlc, LdapServerType.REPLICA, LdapUsage.GET_GROUP_UNIT, staticUnitDN, null);
/*       */       
/*       */ 
/*  6127 */       LdapDynamicGroup.StaticUnit staticUnit = new LdapDynamicGroup.StaticUnit(staticUnitDN, "external", staticUnitAttrs, this);
/*       */       
/*       */ 
/*  6130 */       group.setSubUnits(dynamicUnit, staticUnit);
/*       */     }
/*  6132 */     return group;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   protected void renameAddressesInAllDistributionLists(String oldName, String newName, ReplaceAddressResult replacedAliasPairs)
/*       */   {
/*  6142 */     Map<String, String> changedPairs = new HashMap();
/*       */     
/*  6144 */     changedPairs.put(oldName, newName);
/*  6145 */     for (int i = 0; i < replacedAliasPairs.oldAddrs().length; i++) {
/*  6146 */       String oldAddr = replacedAliasPairs.oldAddrs()[i];
/*  6147 */       String newAddr = replacedAliasPairs.newAddrs()[i];
/*  6148 */       if (!oldAddr.equals(newAddr)) {
/*  6149 */         changedPairs.put(oldAddr, newAddr);
/*       */       }
/*       */     }
/*       */     
/*  6153 */     renameAddressesInAllDistributionLists(changedPairs);
/*       */   }
/*       */   
/*       */   protected void renameAddressesInAllDistributionLists(Map<String, String> changedPairs)
/*       */   {
/*  6158 */     String[] oldAddrs = (String[])changedPairs.keySet().toArray(new String[0]);
/*  6159 */     String[] newAddrs = (String[])changedPairs.values().toArray(new String[0]);
/*       */     
/*  6161 */     List<DistributionList> lists = null;
/*  6162 */     Map<String, String[]> attrs = null;
/*       */     try
/*       */     {
/*  6165 */       lists = getAllDistributionListsForAddresses(oldAddrs, false);
/*       */     } catch (ServiceException se) {
/*  6167 */       ZimbraLog.account.warn("unable to rename addr " + oldAddrs.toString() + " in all DLs ", se);
/*  6168 */       return;
/*       */     }
/*       */     
/*  6171 */     for (DistributionList list : lists)
/*       */     {
/*       */ 
/*  6174 */       if (attrs == null) {
/*  6175 */         attrs = new HashMap();
/*  6176 */         attrs.put("-zimbraMailForwardingAddress", oldAddrs);
/*  6177 */         attrs.put("+zimbraMailForwardingAddress", newAddrs);
/*       */       }
/*       */       try {
/*  6180 */         modifyAttrs(list, attrs);
/*       */ 
/*       */       }
/*       */       catch (ServiceException se)
/*       */       {
/*  6185 */         ZimbraLog.account.warn("unable to rename " + oldAddrs.toString() + " to " + newAddrs.toString() + " in DL " + list.getName(), se);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   void removeAddressFromAllDistributionLists(String address)
/*       */   {
/*  6195 */     String[] addrs = { address };
/*  6196 */     removeAddressesFromAllDistributionLists(addrs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public void removeAddressesFromAllDistributionLists(String[] addrs)
/*       */   {
/*  6203 */     List<DistributionList> lists = null;
/*       */     try {
/*  6205 */       lists = getAllDistributionListsForAddresses(addrs, false);
/*       */     } catch (ServiceException se) {
/*  6207 */       StringBuilder sb = new StringBuilder();
/*  6208 */       for (String addr : addrs)
/*  6209 */         sb.append(addr + ", ");
/*  6210 */       ZimbraLog.account.warn("unable to get all DLs for addrs " + sb.toString());
/*  6211 */       return;
/*       */     }
/*       */     
/*  6214 */     for (DistributionList list : lists) {
/*       */       try {
/*  6216 */         removeMembers(list, addrs);
/*       */       }
/*       */       catch (ServiceException se) {
/*  6219 */         StringBuilder sb = new StringBuilder();
/*  6220 */         for (String addr : addrs)
/*  6221 */           sb.append(addr + ", ");
/*  6222 */         ZimbraLog.account.warn("unable to remove " + sb.toString() + " from DL " + list.getName(), se);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   private List<DistributionList> getAllDistributionListsForAddresses(String[] addrs, boolean basicAttrsOnly)
/*       */     throws ServiceException
/*       */   {
/*  6231 */     if ((addrs == null) || (addrs.length == 0))
/*  6232 */       return new ArrayList();
/*  6233 */     String[] attrs = basicAttrsOnly ? this.BASIC_DL_ATTRS : null;
/*       */     
/*  6235 */     SearchDirectoryOptions searchOpts = new SearchDirectoryOptions(attrs);
/*  6236 */     searchOpts.setFilter(this.filterFactory.distributionListsByMemberAddrs(addrs));
/*  6237 */     searchOpts.setTypes(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.distributionlists });
/*  6238 */     searchOpts.setSortOpt(SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*       */     
/*  6240 */     return searchDirectoryInternal(searchOpts);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private List<DistributionList> getAllDirectDLs(LdapProvisioning prov, Entry entry)
/*       */     throws ServiceException
/*       */   {
/*  6260 */     if (!(entry instanceof GroupedEntry)) {
/*  6261 */       throw ServiceException.FAILURE("internal error", null);
/*       */     }
/*       */     
/*  6264 */     EntryCacheDataKey cacheKey = EntryCacheDataKey.GROUPEDENTRY_DIRECT_GROUPIDS;
/*       */     
/*  6266 */     List<String> directGroupIds = (List)entry.getCachedData(cacheKey);
/*       */     
/*  6268 */     List<DistributionList> directGroups = null;
/*       */     
/*  6270 */     if (directGroupIds == null) {
/*  6271 */       String[] addrs = ((GroupedEntry)entry).getAllAddrsAsGroupMember();
/*       */       
/*       */ 
/*  6274 */       directGroups = prov.getAllDistributionListsForAddresses(addrs, true);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  6283 */       directGroupIds = new ArrayList(directGroups.size());
/*  6284 */       List<DistributionList> directGroupsToReturn = new ArrayList(directGroups.size());
/*  6285 */       for (DistributionList group : directGroups) {
/*  6286 */         String groupId = group.getId();
/*  6287 */         directGroupIds.add(groupId);
/*  6288 */         DistributionList cached = getDLFromCache(Key.DistributionListBy.id, groupId);
/*  6289 */         if (cached == null) {
/*  6290 */           putInGroupCache(group);
/*  6291 */           directGroupsToReturn.add(group);
/*       */         } else {
/*  6293 */           directGroupsToReturn.add(cached);
/*       */         }
/*       */       }
/*  6296 */       entry.setCachedData(cacheKey, directGroupIds);
/*  6297 */       return directGroupsToReturn;
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  6305 */     directGroups = new ArrayList();
/*  6306 */     Set<String> idsToRemove = null;
/*  6307 */     for (String groupId : directGroupIds) {
/*  6308 */       DistributionList group = prov.getDLBasic(Key.DistributionListBy.id, groupId);
/*  6309 */       if (group == null)
/*       */       {
/*       */ 
/*  6312 */         if (idsToRemove == null) {
/*  6313 */           idsToRemove = new HashSet();
/*       */         }
/*  6315 */         idsToRemove.add(groupId);
/*       */       } else {
/*  6317 */         directGroups.add(group);
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*  6322 */     if (idsToRemove != null)
/*       */     {
/*  6324 */       List<String> updatedDirectGroupIds = new ArrayList();
/*  6325 */       for (String id : directGroupIds) {
/*  6326 */         if (!idsToRemove.contains(id)) {
/*  6327 */           updatedDirectGroupIds.add(id);
/*       */         }
/*       */       }
/*       */       
/*       */ 
/*  6332 */       entry.setCachedData(cacheKey, updatedDirectGroupIds);
/*       */     }
/*       */     
/*       */ 
/*  6336 */     return directGroups;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public DistributionList getDLBasic(Key.DistributionListBy keyType, String key)
/*       */     throws ServiceException
/*       */   {
/*  6349 */     return getDLBasic(keyType, key, null);
/*       */   }
/*       */   
/*       */ 
/*       */   private DistributionList getDLBasic(Key.DistributionListBy keyType, String key, ZLdapContext zlc)
/*       */     throws ServiceException
/*       */   {
/*  6356 */     Group group = getGroupFromCache(keyType, key);
/*       */     
/*  6358 */     if ((group instanceof DistributionList))
/*  6359 */       return (DistributionList)group;
/*  6360 */     if ((group instanceof DynamicGroup)) {
/*  6361 */       return null;
/*       */     }
/*       */     
/*       */ 
/*  6365 */     DistributionList dl = null;
/*       */     
/*  6367 */     switch (keyType) {
/*       */     case id: 
/*  6369 */       dl = getDistributionListByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.distributionListById(key), zlc, true);
/*       */       
/*  6371 */       break;
/*       */     case name: 
/*  6373 */       dl = getDistributionListByQuery(this.mDIT.mailBranchBaseDN(), this.filterFactory.distributionListByName(key), zlc, true);
/*       */       
/*  6375 */       break;
/*       */     default: 
/*  6377 */       return null;
/*       */     }
/*       */     
/*  6380 */     if (dl != null) {
/*  6381 */       putInGroupCache(dl);
/*       */     }
/*       */     
/*  6384 */     return dl;
/*       */   }
/*       */   
/*       */   private List<DistributionList> getContainingDistributionLists(Entry entry, boolean directOnly, Map<String, String> via)
/*       */     throws ServiceException
/*       */   {
/*  6390 */     List<DistributionList> directDLs = getAllDirectDLs(this, entry);
/*  6391 */     HashSet<String> directDLSet = new HashSet();
/*  6392 */     HashSet<String> checked = new HashSet();
/*  6393 */     List<DistributionList> result = new ArrayList();
/*       */     
/*  6395 */     Stack<DistributionList> dlsToCheck = new Stack();
/*       */     
/*  6397 */     for (DistributionList dl : directDLs) {
/*  6398 */       dlsToCheck.push(dl);
/*  6399 */       directDLSet.add(dl.getName());
/*       */     }
/*       */     DistributionList dl;
/*  6402 */     while (!dlsToCheck.isEmpty()) {
/*  6403 */       dl = (DistributionList)dlsToCheck.pop();
/*  6404 */       if (!checked.contains(dl.getId())) {
/*  6405 */         result.add(dl);
/*  6406 */         checked.add(dl.getId());
/*  6407 */         if (!directOnly)
/*       */         {
/*  6409 */           List<DistributionList> newLists = getAllDirectDLs(this, dl);
/*       */           
/*  6411 */           for (DistributionList newDl : newLists)
/*  6412 */             if (!directDLSet.contains(newDl.getName())) {
/*  6413 */               if (via != null) {
/*  6414 */                 via.put(newDl.getName(), dl.getName());
/*       */               }
/*  6416 */               dlsToCheck.push(newDl);
/*       */             }
/*       */         }
/*       */       } }
/*  6420 */     Collections.sort(result);
/*  6421 */     return result;
/*       */   }
/*       */   
/*       */   public Set<String> getDistributionLists(Account acct)
/*       */     throws ServiceException
/*       */   {
/*  6427 */     Set<String> dls = (Set)acct.getCachedData(EntryCacheDataKey.ACCOUNT_DLS);
/*  6428 */     if (dls != null) {
/*  6429 */       return dls;
/*       */     }
/*  6431 */     dls = getDistributionListIds(acct, false);
/*  6432 */     acct.setCachedData(EntryCacheDataKey.ACCOUNT_DLS, dls);
/*  6433 */     return dls;
/*       */   }
/*       */   
/*       */   public Set<String> getDirectDistributionLists(Account acct)
/*       */     throws ServiceException
/*       */   {
/*  6439 */     Set<String> dls = (Set)acct.getCachedData(EntryCacheDataKey.ACCOUNT_DIRECT_DLS);
/*  6440 */     if (dls != null) {
/*  6441 */       return dls;
/*       */     }
/*  6443 */     dls = getDistributionListIds(acct, true);
/*  6444 */     acct.setCachedData(EntryCacheDataKey.ACCOUNT_DIRECT_DLS, dls);
/*  6445 */     return dls;
/*       */   }
/*       */   
/*       */   private Set<String> getDistributionListIds(Account acct, boolean directOnly)
/*       */     throws ServiceException
/*       */   {
/*  6451 */     Set<String> dls = new HashSet();
/*       */     
/*  6453 */     List<DistributionList> lists = getDistributionLists(acct, directOnly, null);
/*       */     
/*  6455 */     for (DistributionList dl : lists) {
/*  6456 */       dls.add(dl.getId());
/*       */     }
/*  6458 */     dls = Collections.unmodifiableSet(dls);
/*  6459 */     return dls;
/*       */   }
/*       */   
/*       */   public boolean inDistributionList(Account acct, String zimbraId) throws ServiceException
/*       */   {
/*  6464 */     return getDistributionLists(acct).contains(zimbraId);
/*       */   }
/*       */   
/*       */ 
/*       */   public boolean inDistributionList(DistributionList list, String zimbraId)
/*       */     throws ServiceException
/*       */   {
/*  6471 */     Provisioning.GroupMembership groupMembership = getGroupMembership(list, false);
/*  6472 */     return groupMembership.groupIds().contains(zimbraId);
/*       */   }
/*       */   
/*       */   public List<DistributionList> getDistributionLists(Account acct, boolean directOnly, Map<String, String> via)
/*       */     throws ServiceException
/*       */   {
/*  6478 */     return getContainingDistributionLists(acct, directOnly, via);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public List<?> getAllAccounts(Domain domain)
/*       */     throws ServiceException
/*       */   {
/*  6489 */     SearchAccountsOptions opts = new SearchAccountsOptions(domain);
/*  6490 */     opts.setFilter(this.filterFactory.allAccountsOnly());
/*  6491 */     opts.setIncludeType(SearchAccountsOptions.IncludeType.ACCOUNTS_ONLY);
/*  6492 */     opts.setSortOpt(SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*  6493 */     return searchDirectory(opts);
/*       */   }
/*       */   
/*       */   public void getAllAccounts(Domain domain, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6499 */     SearchAccountsOptions opts = new SearchAccountsOptions(domain);
/*  6500 */     opts.setFilter(this.filterFactory.allAccountsOnly());
/*  6501 */     opts.setIncludeType(SearchAccountsOptions.IncludeType.ACCOUNTS_ONLY);
/*  6502 */     searchDirectory(opts, visitor);
/*       */   }
/*       */   
/*       */   public void getAllAccounts(Domain domain, Server server, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6508 */     if (server != null) {
/*  6509 */       SearchAccountsOptions searchOpts = new SearchAccountsOptions(domain);
/*  6510 */       searchOpts.setIncludeType(SearchAccountsOptions.IncludeType.ACCOUNTS_ONLY);
/*  6511 */       searchAccountsOnServerInternal(server, searchOpts, visitor);
/*       */     } else {
/*  6513 */       getAllAccounts(domain, visitor);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<?> getAllCalendarResources(Domain domain) throws ServiceException
/*       */   {
/*  6519 */     SearchDirectoryOptions searchOpts = new SearchDirectoryOptions(domain);
/*  6520 */     searchOpts.setFilter(this.mDIT.filterCalendarResourcesByDomain(domain));
/*  6521 */     searchOpts.setTypes(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.resources });
/*  6522 */     searchOpts.setSortOpt(SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*  6523 */     return searchDirectoryInternal(searchOpts);
/*       */   }
/*       */   
/*       */   public void getAllCalendarResources(Domain domain, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6529 */     SearchDirectoryOptions searchOpts = new SearchDirectoryOptions(domain);
/*  6530 */     searchOpts.setFilter(this.mDIT.filterCalendarResourcesByDomain(domain));
/*  6531 */     searchOpts.setTypes(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.resources });
/*  6532 */     searchDirectoryInternal(searchOpts, visitor);
/*       */   }
/*       */   
/*       */   public void getAllCalendarResources(Domain domain, Server server, NamedEntry.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6538 */     if (server != null) {
/*  6539 */       SearchAccountsOptions searchOpts = new SearchAccountsOptions(domain);
/*  6540 */       searchOpts.setIncludeType(SearchAccountsOptions.IncludeType.CALENDAR_RESOURCES_ONLY);
/*  6541 */       searchAccountsOnServerInternal(server, searchOpts, visitor);
/*       */     } else {
/*  6543 */       getAllCalendarResources(domain, visitor);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<?> getAllDistributionLists(Domain domain) throws ServiceException
/*       */   {
/*  6549 */     SearchDirectoryOptions searchOpts = new SearchDirectoryOptions(domain);
/*  6550 */     searchOpts.setFilter(this.mDIT.filterDistributionListsByDomain(domain));
/*  6551 */     searchOpts.setTypes(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.distributionlists });
/*  6552 */     searchOpts.setSortOpt(SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*  6553 */     return searchDirectoryInternal(searchOpts);
/*       */   }
/*       */   
/*       */ 
/*       */   public Provisioning.SearchGalResult autoCompleteGal(Domain domain, String query, GalSearchType type, int limit, GalContact.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6560 */     Provisioning.SearchGalResult searchResult = Provisioning.SearchGalResult.newSearchGalResult(visitor);
/*       */     
/*  6562 */     GalSearchParams params = new GalSearchParams(domain, null);
/*  6563 */     params.setQuery(query);
/*  6564 */     params.setType(type);
/*  6565 */     params.setOp(GalOp.autocomplete);
/*  6566 */     params.setLimit(limit);
/*  6567 */     params.setGalResult(searchResult);
/*       */     
/*  6569 */     LdapOnlyGalSearchResultCallback callback = new LdapOnlyGalSearchResultCallback(params, visitor);
/*       */     
/*  6571 */     params.setResultCallback(callback);
/*       */     
/*  6573 */     GalSearchControl gal = new GalSearchControl(params);
/*  6574 */     gal.ldapSearch();
/*       */     
/*  6576 */     return searchResult;
/*       */   }
/*       */   
/*       */ 
/*       */   public Provisioning.SearchGalResult searchGal(Domain domain, String query, GalSearchType type, int limit, GalContact.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6583 */     Provisioning.SearchGalResult searchResult = Provisioning.SearchGalResult.newSearchGalResult(visitor);
/*       */     
/*  6585 */     GalSearchParams params = new GalSearchParams(domain, null);
/*  6586 */     params.setQuery(query);
/*  6587 */     params.setType(type);
/*  6588 */     params.setOp(GalOp.search);
/*  6589 */     params.setLimit(limit);
/*  6590 */     params.setGalResult(searchResult);
/*       */     
/*  6592 */     LdapOnlyGalSearchResultCallback callback = new LdapOnlyGalSearchResultCallback(params, visitor);
/*       */     
/*  6594 */     params.setResultCallback(callback);
/*       */     
/*  6596 */     GalSearchControl gal = new GalSearchControl(params);
/*  6597 */     gal.ldapSearch();
/*  6598 */     return searchResult;
/*       */   }
/*       */   
/*       */   public Provisioning.SearchGalResult syncGal(Domain domain, String token, GalContact.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6604 */     Provisioning.SearchGalResult searchResult = Provisioning.SearchGalResult.newSearchGalResult(visitor);
/*       */     
/*  6606 */     GalSearchParams params = new GalSearchParams(domain, null);
/*  6607 */     params.setQuery("");
/*  6608 */     params.setToken(token);
/*  6609 */     params.setType(GalSearchType.all);
/*  6610 */     params.setOp(GalOp.sync);
/*  6611 */     params.setFetchGroupMembers(true);
/*  6612 */     params.setNeedSMIMECerts(true);
/*  6613 */     params.setGalResult(searchResult);
/*       */     
/*  6615 */     LdapOnlyGalSearchResultCallback callback = new LdapOnlyGalSearchResultCallback(params, visitor);
/*       */     
/*  6617 */     params.setResultCallback(callback);
/*       */     
/*  6619 */     GalSearchControl gal = new GalSearchControl(params);
/*  6620 */     gal.ldapSearch();
/*  6621 */     return searchResult;
/*       */   }
/*       */   
/*       */   private static class LdapOnlyGalSearchResultCallback extends GalSearchResultCallback {
/*       */     GalContact.Visitor visitor;
/*       */     String newToken;
/*       */     boolean hasMore;
/*       */     
/*       */     LdapOnlyGalSearchResultCallback(GalSearchParams params, GalContact.Visitor visitor) {
/*  6630 */       super();
/*  6631 */       this.visitor = visitor;
/*       */     }
/*       */     
/*       */     private String getNewToken() {
/*  6635 */       return this.newToken;
/*       */     }
/*       */     
/*       */ 
/*       */     public void reset(GalSearchParams params) {}
/*       */     
/*       */ 
/*       */     public void visit(GalContact c)
/*       */       throws ServiceException
/*       */     {
/*  6645 */       this.visitor.visit(c);
/*       */     }
/*       */     
/*       */     public void setNewToken(String newToken)
/*       */     {
/*  6650 */       this.newToken = newToken;
/*       */     }
/*       */     
/*       */     public void setHasMoreResult(boolean more)
/*       */     {
/*  6655 */       this.hasMore = more;
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */     public void setGalDefinitionLastModified(String timestamp) {}
/*       */     
/*       */ 
/*       */     public Element getResponse()
/*       */     {
/*  6665 */       throw new UnsupportedOperationException();
/*       */     }
/*       */     
/*       */     public boolean passThruProxiedGalAcctResponse()
/*       */     {
/*  6670 */       throw new UnsupportedOperationException();
/*       */     }
/*       */     
/*       */     public void handleProxiedResponse(Element resp)
/*       */     {
/*  6675 */       throw new UnsupportedOperationException();
/*       */     }
/*       */     
/*       */     public void setNewToken(GalSyncToken newToken)
/*       */     {
/*  6680 */       throw new UnsupportedOperationException();
/*       */     }
/*       */     
/*       */     public void setSortBy(String sortBy)
/*       */     {
/*  6685 */       throw new UnsupportedOperationException();
/*       */     }
/*       */     
/*       */     public void setQueryOffset(int offset)
/*       */     {
/*  6690 */       throw new UnsupportedOperationException();
/*       */     }
/*       */   }
/*       */   
/*       */   public void searchGal(GalSearchParams params)
/*       */     throws ServiceException
/*       */   {
/*  6697 */     LdapGalSearch.galSearch(params);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   public Provisioning.SearchGalResult searchGal(Domain d, String n, GalSearchType type, Provisioning.GalMode galMode, String token)
/*       */     throws ServiceException
/*       */   {
/*  6706 */     return searchGal(d, n, type, galMode, token, null);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private Provisioning.SearchGalResult searchGal(Domain d, String n, GalSearchType type, Provisioning.GalMode galMode, String token, GalContact.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6717 */     GalOp galOp = token != null ? GalOp.sync : GalOp.search;
/*       */     
/*  6719 */     n = LdapUtil.escapeSearchFilterArg(n);
/*       */     
/*  6721 */     int maxResults = token != null ? 0 : d.getIntAttr("zimbraGalMaxResults", 100);
/*  6722 */     if (type == GalSearchType.resource)
/*  6723 */       return searchResourcesGal(d, n, maxResults, token, galOp, visitor);
/*  6724 */     if (type == GalSearchType.group) {
/*  6725 */       return searchGroupsGal(d, n, maxResults, null, galOp, null);
/*       */     }
/*  6727 */     Provisioning.GalMode mode = galMode != null ? galMode : Provisioning.GalMode.fromString(d.getAttr("zimbraGalMode"));
/*  6728 */     Provisioning.SearchGalResult results = null;
/*  6729 */     if ((mode == null) || (mode == Provisioning.GalMode.zimbra)) {
/*  6730 */       results = searchZimbraGal(d, n, maxResults, token, galOp, visitor);
/*  6731 */     } else if (mode == Provisioning.GalMode.ldap) {
/*  6732 */       results = searchLdapGal(d, n, maxResults, token, galOp, visitor);
/*  6733 */     } else if (mode == Provisioning.GalMode.both) {
/*  6734 */       results = searchZimbraGal(d, n, maxResults / 2, token, galOp, visitor);
/*  6735 */       Provisioning.SearchGalResult ldapResults = searchLdapGal(d, n, maxResults / 2, token, galOp, visitor);
/*  6736 */       if (ldapResults != null) {
/*  6737 */         results.addMatches(ldapResults);
/*  6738 */         results.setToken(LdapUtil.getLaterTimestamp(results.getToken(), ldapResults.getToken()));
/*       */       }
/*       */     } else {
/*  6741 */       results = searchZimbraGal(d, n, maxResults, token, galOp, visitor);
/*       */     }
/*  6743 */     if (results == null) { results = Provisioning.SearchGalResult.newSearchGalResult(visitor);
/*       */     }
/*  6745 */     if (type == GalSearchType.all) {
/*  6746 */       Provisioning.SearchGalResult resourceResults = null;
/*  6747 */       if (maxResults == 0) {
/*  6748 */         resourceResults = searchResourcesGal(d, n, 0, token, galOp, visitor);
/*       */       } else {
/*  6750 */         int room = maxResults - results.getNumMatches();
/*  6751 */         if (room > 0)
/*  6752 */           resourceResults = searchResourcesGal(d, n, room, token, galOp, visitor);
/*       */       }
/*  6754 */       if (resourceResults != null) {
/*  6755 */         results.addMatches(resourceResults);
/*  6756 */         results.setToken(LdapUtil.getLaterTimestamp(results.getToken(), resourceResults.getToken()));
/*       */       }
/*       */     }
/*       */     
/*  6760 */     return results;
/*       */   }
/*       */   
/*       */   public static String getFilterDef(String name) throws ServiceException {
/*  6764 */     String[] queryExprs = Provisioning.getInstance().getConfig().getMultiAttr("zimbraGalLdapFilterDef");
/*  6765 */     String fname = name + ":";
/*  6766 */     String queryExpr = null;
/*  6767 */     for (int i = 0; i < queryExprs.length; i++) {
/*  6768 */       if (queryExprs[i].startsWith(fname)) {
/*  6769 */         queryExpr = queryExprs[i].substring(fname.length());
/*       */       }
/*       */     }
/*       */     
/*  6773 */     if (queryExpr == null) {
/*  6774 */       ZimbraLog.gal.warn("missing filter def " + name + " in " + "zimbraGalLdapFilterDef");
/*       */     }
/*  6776 */     return queryExpr;
/*       */   }
/*       */   
/*       */   private synchronized LdapGalMapRules getGalRules(Domain d, boolean isZimbraGal) {
/*  6780 */     LdapGalMapRules rules = (LdapGalMapRules)d.getCachedData("GAL_RULES");
/*  6781 */     if (rules == null) {
/*  6782 */       rules = new LdapGalMapRules(d, isZimbraGal);
/*  6783 */       d.setCachedData("GAL_RULES", rules);
/*       */     }
/*  6785 */     return rules;
/*       */   }
/*       */   
/*       */   private Provisioning.SearchGalResult searchResourcesGal(Domain d, String n, int maxResults, String token, GalOp galOp, GalContact.Visitor visitor) throws ServiceException
/*       */   {
/*  6790 */     return searchZimbraWithNamedFilter(d, galOp, GalNamedFilter.getZimbraCalendarResourceFilter(galOp), n, maxResults, token, visitor);
/*       */   }
/*       */   
/*       */   private Provisioning.SearchGalResult searchGroupsGal(Domain d, String n, int maxResults, String token, GalOp galOp, GalContact.Visitor visitor) throws ServiceException
/*       */   {
/*  6795 */     return searchZimbraWithNamedFilter(d, galOp, GalNamedFilter.getZimbraGroupFilter(galOp), n, maxResults, token, visitor);
/*       */   }
/*       */   
/*       */   private Provisioning.SearchGalResult searchZimbraGal(Domain d, String n, int maxResults, String token, GalOp galOp, GalContact.Visitor visitor) throws ServiceException
/*       */   {
/*  6800 */     return searchZimbraWithNamedFilter(d, galOp, GalNamedFilter.getZimbraAcountFilter(galOp), n, maxResults, token, visitor);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private Provisioning.SearchGalResult searchZimbraWithNamedFilter(Domain domain, GalOp galOp, String filterName, String n, int maxResults, String token, GalContact.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6812 */     GalParams.ZimbraGalParams galParams = new GalParams.ZimbraGalParams(domain, galOp);
/*       */     
/*  6814 */     String queryExpr = getFilterDef(filterName);
/*  6815 */     String query = null;
/*       */     
/*  6817 */     String tokenize = GalUtil.tokenizeKey(galParams, galOp);
/*  6818 */     if (queryExpr != null) {
/*  6819 */       if (token != null) {
/*  6820 */         n = "";
/*       */       }
/*  6822 */       query = GalUtil.expandFilter(tokenize, queryExpr, n, token);
/*       */     }
/*       */     
/*  6825 */     Provisioning.SearchGalResult result = Provisioning.SearchGalResult.newSearchGalResult(visitor);
/*  6826 */     result.setTokenizeKey(tokenize);
/*  6827 */     if (query == null) {
/*  6828 */       ZimbraLog.gal.warn("searchZimbraWithNamedFilter query is null");
/*  6829 */       return result;
/*       */     }
/*       */     
/*       */ 
/*  6833 */     if (!query.startsWith("(")) {
/*  6834 */       query = "(" + query + ")";
/*       */     }
/*  6836 */     query = "(&" + query + "(!(zimbraHideInGal=TRUE)))";
/*       */     
/*  6838 */     ZLdapContext zlc = null;
/*       */     try {
/*  6840 */       zlc = LdapClient.getContext(LdapUsage.fromGalOpLegacy(galOp));
/*  6841 */       LdapGalSearch.searchGal(zlc, com.zimbra.cs.gal.GalSearchConfig.GalType.zimbra, galParams.pageSize(), galParams.searchBase(), query, maxResults, getGalRules(domain, true), token, result);
/*       */ 
/*       */ 
/*       */ 
/*       */     }
/*       */     finally
/*       */     {
/*       */ 
/*       */ 
/*       */ 
/*  6851 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/*       */ 
/*  6855 */     return result;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private Provisioning.SearchGalResult searchLdapGal(Domain domain, String n, int maxResults, String token, GalOp galOp, GalContact.Visitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  6866 */     GalParams.ExternalGalParams galParams = new GalParams.ExternalGalParams(domain, galOp);
/*       */     
/*  6868 */     LdapGalMapRules rules = getGalRules(domain, false);
/*       */     try {
/*  6870 */       return LdapGalSearch.searchLdapGal(galParams, galOp, n, maxResults, rules, token, visitor);
/*       */ 
/*       */ 
/*       */     }
/*       */     catch (ServiceException e)
/*       */     {
/*       */ 
/*       */ 
/*  6878 */       throw ServiceException.FAILURE("unable to search GAL", e);
/*       */     }
/*       */   }
/*       */   
/*       */   public void addMembers(DistributionList list, String[] members) throws ServiceException
/*       */   {
/*  6884 */     LdapDistributionList ldl = (LdapDistributionList)list;
/*  6885 */     addDistributionListMembers(ldl, members);
/*       */   }
/*       */   
/*       */   public void removeMembers(DistributionList list, String[] members) throws ServiceException
/*       */   {
/*  6890 */     LdapDistributionList ldl = (LdapDistributionList)list;
/*  6891 */     removeDistributionListMembers(ldl, members);
/*       */   }
/*       */   
/*       */   private void addDistributionListMembers(DistributionList dl, String[] members) throws ServiceException
/*       */   {
/*  6896 */     Set<String> existing = dl.getMultiAttrSet("zimbraMailForwardingAddress");
/*  6897 */     Set<String> mods = new HashSet();
/*       */     
/*       */ 
/*  6900 */     AddrsOfEntry addrsOfDL = getAllAddressesOfEntry(dl.getName());
/*       */     
/*  6902 */     for (int i = 0; i < members.length; i++) {
/*  6903 */       String memberName = members[i].toLowerCase();
/*  6904 */       memberName = IDNUtil.toAsciiEmail(memberName);
/*       */       
/*  6906 */       if (addrsOfDL.isIn(memberName)) {
/*  6907 */         throw ServiceException.INVALID_REQUEST("Cannot add self as a member: " + memberName, null);
/*       */       }
/*       */       
/*  6910 */       if (getDynamicGroupBasic(Key.DistributionListBy.name, memberName, null) != null) {
/*  6911 */         throw ServiceException.INVALID_REQUEST("Cannot add dynamic group as a member: " + memberName, null);
/*       */       }
/*       */       
/*  6914 */       if (!existing.contains(memberName)) {
/*  6915 */         mods.add(memberName);
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*  6920 */         Account acct = get(Key.AccountBy.name, memberName);
/*  6921 */         if (acct != null) {
/*  6922 */           clearUpwardMembershipCache(acct);
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */         }
/*       */         else
/*       */         {
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  6935 */           removeGroupFromCache(Key.DistributionListBy.name, memberName);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*  6940 */     if (mods.isEmpty())
/*       */     {
/*  6942 */       return;
/*       */     }
/*       */     
/*  6945 */     PermissionCache.invalidateCache();
/*  6946 */     cleanGroupMembersCache(dl);
/*       */     
/*  6948 */     Map<String, String[]> modmap = new HashMap();
/*  6949 */     modmap.put("+zimbraMailForwardingAddress", mods.toArray(new String[0]));
/*  6950 */     modifyAttrs(dl, modmap, true);
/*       */   }
/*       */   
/*       */   private void removeDistributionListMembers(DistributionList dl, String[] members) throws ServiceException
/*       */   {
/*  6955 */     Set<String> curMembers = dl.getMultiAttrSet("zimbraMailForwardingAddress");
/*       */     
/*       */ 
/*  6958 */     Set<String> existing = new TreeSet(String.CASE_INSENSITIVE_ORDER);
/*  6959 */     existing.addAll(curMembers);
/*       */     
/*  6961 */     Set<String> mods = new HashSet();
/*  6962 */     HashSet<String> failed = new HashSet();
/*       */     
/*  6964 */     for (int i = 0; i < members.length; i++) {
/*  6965 */       String memberName = members[i].toLowerCase();
/*  6966 */       memberName = IDNUtil.toAsciiEmail(memberName);
/*  6967 */       if (memberName.length() == 0) {
/*  6968 */         throw ServiceException.INVALID_REQUEST("invalid member email address: " + memberName, null);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  6978 */       AddrsOfEntry addrsOfEntry = getAllAddressesOfEntry(memberName);
/*  6979 */       List<String> allAddrs = addrsOfEntry.getAll();
/*       */       
/*  6981 */       if (!mods.contains(memberName))
/*       */       {
/*  6983 */         if (existing.contains(memberName)) {
/*  6984 */           if (!allAddrs.isEmpty()) {
/*  6985 */             mods.addAll(allAddrs);
/*       */           } else {
/*  6987 */             mods.add(memberName);
/*       */           }
/*       */         } else {
/*  6990 */           boolean inList = false;
/*  6991 */           if (allAddrs.size() > 0)
/*       */           {
/*  6993 */             for (String addr : allAddrs) {
/*  6994 */               if (!inList) {
/*       */                 break;
/*       */               }
/*  6997 */               if (existing.contains(addr)) {
/*  6998 */                 mods.addAll(allAddrs);
/*  6999 */                 inList = true;
/*       */               }
/*       */             }
/*       */           }
/*  7003 */           if (!inList) {
/*  7004 */             failed.add(memberName);
/*       */           }
/*       */         }
/*       */       }
/*       */       
/*  7009 */       String primary = addrsOfEntry.getPrimary();
/*  7010 */       if (primary != null) {
/*  7011 */         if (addrsOfEntry.isAccount()) {
/*  7012 */           Account acct = getFromCache(Key.AccountBy.name, primary);
/*  7013 */           if (acct != null)
/*  7014 */             clearUpwardMembershipCache(acct);
/*       */         } else {
/*  7016 */           removeGroupFromCache(Key.DistributionListBy.name, primary);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*  7021 */     if (!failed.isEmpty()) {
/*  7022 */       StringBuilder sb = new StringBuilder();
/*  7023 */       Iterator<String> iter = failed.iterator();
/*       */       for (;;) {
/*  7025 */         sb.append((String)iter.next());
/*  7026 */         if (!iter.hasNext())
/*       */           break;
/*  7028 */         sb.append(",");
/*       */       }
/*  7030 */       throw AccountServiceException.NO_SUCH_MEMBER(dl.getName(), sb.toString());
/*       */     }
/*       */     
/*  7033 */     if (mods.isEmpty()) {
/*  7034 */       throw ServiceException.INVALID_REQUEST("empty remove set", null);
/*       */     }
/*       */     
/*  7037 */     PermissionCache.invalidateCache();
/*  7038 */     cleanGroupMembersCache(dl);
/*       */     
/*  7040 */     Map<String, String[]> modmap = new HashMap();
/*  7041 */     modmap.put("-zimbraMailForwardingAddress", mods.toArray(new String[0]));
/*  7042 */     modifyAttrs(dl, modmap);
/*       */   }
/*       */   
/*       */   private void clearUpwardMembershipCache(Account acct)
/*       */   {
/*  7047 */     acct.setCachedData(EntryCacheDataKey.ACCOUNT_DLS, null);
/*  7048 */     acct.setCachedData(EntryCacheDataKey.ACCOUNT_DIRECT_DLS, null);
/*  7049 */     acct.setCachedData(EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP, null);
/*  7050 */     acct.setCachedData(EntryCacheDataKey.GROUPEDENTRY_MEMBERSHIP_ADMINS_ONLY, null);
/*  7051 */     acct.setCachedData(EntryCacheDataKey.GROUPEDENTRY_DIRECT_GROUPIDS.getKeyName(), null); }
/*       */   
/*       */   private class AddrsOfEntry { private AddrsOfEntry() {}
/*       */     
/*  7055 */     List<String> mAllAddrs = new ArrayList();
/*  7056 */     String mPrimary = null;
/*  7057 */     boolean mIsAccount = false;
/*       */     
/*       */     void setPrimary(String primary) {
/*  7060 */       this.mPrimary = primary;
/*  7061 */       add(primary);
/*       */     }
/*       */     
/*       */     void setIsAccount(boolean isAccount) {
/*  7065 */       this.mIsAccount = isAccount;
/*       */     }
/*       */     
/*       */     void add(String addr) {
/*  7069 */       this.mAllAddrs.add(addr);
/*       */     }
/*       */     
/*       */     void addAll(String[] addrs) {
/*  7073 */       this.mAllAddrs.addAll(Arrays.asList(addrs));
/*       */     }
/*       */     
/*       */     List<String> getAll() {
/*  7077 */       return this.mAllAddrs;
/*       */     }
/*       */     
/*       */     String getPrimary() {
/*  7081 */       return this.mPrimary;
/*       */     }
/*       */     
/*       */     boolean isAccount() {
/*  7085 */       return this.mIsAccount;
/*       */     }
/*       */     
/*       */     boolean isIn(String addr) {
/*  7089 */       return this.mAllAddrs.contains(addr.toLowerCase());
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private AddrsOfEntry getAllAddressesOfEntry(String name)
/*       */   {
/*  7099 */     String primary = null;
/*  7100 */     String[] aliases = null;
/*  7101 */     AddrsOfEntry addrs = new AddrsOfEntry(null);
/*       */     
/*       */ 
/*       */     try
/*       */     {
/*  7106 */       Account acct = getAccountByName(name, false, false);
/*  7107 */       if (acct != null) {
/*  7108 */         addrs.setIsAccount(true);
/*  7109 */         primary = acct.getName();
/*  7110 */         aliases = acct.getMailAlias();
/*       */       } else {
/*  7112 */         DistributionList dl = get(Key.DistributionListBy.name, name);
/*  7113 */         if (dl != null) {
/*  7114 */           primary = dl.getName();
/*  7115 */           aliases = dl.getAliases();
/*       */         }
/*       */       }
/*       */     }
/*       */     catch (ServiceException se) {}
/*       */     
/*       */ 
/*  7122 */     if (primary != null)
/*  7123 */       addrs.setPrimary(primary);
/*  7124 */     if (aliases != null) {
/*  7125 */       addrs.addAll(aliases);
/*       */     }
/*  7127 */     return addrs;
/*       */   }
/*       */   
/*       */   private List<Identity> getIdentitiesByQuery(LdapEntry entry, ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*  7132 */     List<Identity> result = new ArrayList();
/*       */     try
/*       */     {
/*  7135 */       String base = entry.getDN();
/*  7136 */       ZSearchResultEnumeration ne = this.helper.searchDir(base, filter, ZSearchControls.SEARCH_CTLS_SUBTREE(), initZlc, LdapServerType.REPLICA);
/*       */       
/*  7138 */       while (ne.hasMore()) {
/*  7139 */         ZSearchResultEntry sr = ne.next();
/*  7140 */         result.add(new LdapIdentity((Account)entry, sr.getDN(), sr.getAttributes(), this));
/*       */       }
/*  7142 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  7144 */       throw ServiceException.FAILURE("unable to lookup identity via query: " + filter.toFilterString() + " message: " + e.getMessage(), e);
/*       */     }
/*       */     
/*  7147 */     return result;
/*       */   }
/*       */   
/*       */   private Identity getIdentityByName(LdapEntry entry, String name, ZLdapContext zlc) throws ServiceException {
/*  7151 */     List<Identity> result = getIdentitiesByQuery(entry, this.filterFactory.identityByName(name), zlc);
/*  7152 */     return result.isEmpty() ? null : (Identity)result.get(0);
/*       */   }
/*       */   
/*       */   private String getIdentityDn(LdapEntry entry, String name) {
/*  7156 */     return "zimbraPrefIdentityName=" + LdapUtil.escapeRDNValue(name) + "," + entry.getDN();
/*       */   }
/*       */   
/*       */   private void validateIdentityAttrs(Map<String, Object> attrs) throws ServiceException {
/*  7160 */     Set<String> validAttrs = AttributeManager.getInstance().getLowerCaseAttrsInClass(AttributeClass.identity);
/*  7161 */     for (String key : attrs.keySet()) {
/*  7162 */       if (!validAttrs.contains(key.toLowerCase())) {
/*  7163 */         throw ServiceException.INVALID_REQUEST("unable to modify attr: " + key, null);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   public Identity createIdentity(Account account, String identityName, Map<String, Object> identityAttrs)
/*       */     throws ServiceException
/*       */   {
/*  7174 */     return createIdentity(account, identityName, identityAttrs, false);
/*       */   }
/*       */   
/*       */ 
/*       */   public Identity restoreIdentity(Account account, String identityName, Map<String, Object> identityAttrs)
/*       */     throws ServiceException
/*       */   {
/*  7181 */     return createIdentity(account, identityName, identityAttrs, true);
/*       */   }
/*       */   
/*       */   private Identity createIdentity(Account account, String identityName, Map<String, Object> identityAttrs, boolean restoring)
/*       */     throws ServiceException
/*       */   {
/*  7187 */     removeAttrIgnoreCase("objectclass", identityAttrs);
/*  7188 */     validateIdentityAttrs(identityAttrs);
/*       */     
/*  7190 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*       */     
/*  7192 */     if (ldapEntry == null) {
/*  7193 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*  7195 */     if (identityName.equalsIgnoreCase("DEFAULT")) {
/*  7196 */       throw AccountServiceException.IDENTITY_EXISTS(identityName);
/*       */     }
/*  7198 */     List<Identity> existing = getAllIdentities(account);
/*  7199 */     if (existing.size() >= account.getLongAttr("zimbraIdentityMaxNumEntries", 20L)) {
/*  7200 */       throw AccountServiceException.TOO_MANY_IDENTITIES();
/*       */     }
/*  7202 */     account.setCachedData("LdapProvisioning.IDENTITY_CACHE", null);
/*       */     
/*  7204 */     boolean checkImmutable = !restoring;
/*  7205 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  7206 */     AttributeManager.getInstance().preModify(identityAttrs, null, callbackContext, checkImmutable);
/*       */     
/*  7208 */     ZLdapContext zlc = null;
/*       */     try {
/*  7210 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_IDENTITY);
/*       */       
/*  7212 */       String dn = getIdentityDn(ldapEntry, identityName);
/*       */       
/*  7214 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  7215 */       entry.setDN(dn);
/*  7216 */       entry.mapToAttrs(identityAttrs);
/*       */       
/*  7218 */       entry.setAttr("objectClass", "zimbraIdentity");
/*       */       
/*  7220 */       if (!entry.hasAttribute("zimbraPrefIdentityId")) {
/*  7221 */         String identityId = LdapUtil.generateUUID();
/*  7222 */         entry.setAttr("zimbraPrefIdentityId", identityId);
/*       */       }
/*  7224 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*       */       
/*  7226 */       zlc.createEntry(entry);
/*       */       
/*  7228 */       Identity identity = getIdentityByName(ldapEntry, identityName, zlc);
/*  7229 */       AttributeManager.getInstance().postModify(identityAttrs, identity, callbackContext);
/*       */       
/*  7231 */       return identity;
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  7233 */       throw AccountServiceException.IDENTITY_EXISTS(identityName);
/*       */     } catch (LdapException e) {
/*  7235 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  7237 */       throw e;
/*       */     } catch (ServiceException e) {
/*  7239 */       throw ServiceException.FAILURE("unable to create identity " + identityName, e);
/*       */     } finally {
/*  7241 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   public void modifyIdentity(Account account, String identityName, Map<String, Object> identityAttrs)
/*       */     throws ServiceException
/*       */   {
/*  7249 */     removeAttrIgnoreCase("objectclass", identityAttrs);
/*       */     
/*  7251 */     validateIdentityAttrs(identityAttrs);
/*       */     
/*  7253 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*       */     
/*  7255 */     if (ldapEntry == null) {
/*  7256 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*       */     
/*  7259 */     account.setCachedData("LdapProvisioning.IDENTITY_CACHE", null);
/*       */     
/*  7261 */     if (identityName.equalsIgnoreCase("DEFAULT")) {
/*  7262 */       modifyAttrs(account, identityAttrs);
/*       */     }
/*       */     else {
/*  7265 */       LdapIdentity identity = (LdapIdentity)getIdentityByName(ldapEntry, identityName, null);
/*  7266 */       if (identity == null) {
/*  7267 */         throw AccountServiceException.NO_SUCH_IDENTITY(identityName);
/*       */       }
/*  7269 */       String name = (String)identityAttrs.get("zimbraPrefIdentityName");
/*  7270 */       boolean newName = (name != null) && (!name.equals(identityName));
/*  7271 */       if (newName) { identityAttrs.remove("zimbraPrefIdentityName");
/*       */       }
/*  7273 */       modifyAttrs(identity, identityAttrs, true);
/*  7274 */       if (newName)
/*       */       {
/*  7276 */         account.setCachedData("LdapProvisioning.IDENTITY_CACHE", null);
/*  7277 */         renameIdentity(ldapEntry, identity, name);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */   private void renameIdentity(LdapEntry entry, LdapIdentity identity, String newIdentityName)
/*       */     throws ServiceException
/*       */   {
/*  7286 */     if (identity.getName().equalsIgnoreCase("DEFAULT")) {
/*  7287 */       throw ServiceException.INVALID_REQUEST("can't rename default identity", null);
/*       */     }
/*  7289 */     ZLdapContext zlc = null;
/*       */     try {
/*  7291 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_IDENTITY);
/*  7292 */       String newDn = getIdentityDn(entry, newIdentityName);
/*  7293 */       zlc.renameEntry(identity.getDN(), newDn);
/*       */     } catch (ServiceException e) {
/*  7295 */       throw ServiceException.FAILURE("unable to rename identity: " + newIdentityName, e);
/*       */     } finally {
/*  7297 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteIdentity(Account account, String identityName) throws ServiceException
/*       */   {
/*  7303 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7304 */     if (ldapEntry == null) {
/*  7305 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*  7307 */     if (identityName.equalsIgnoreCase("DEFAULT")) {
/*  7308 */       throw ServiceException.INVALID_REQUEST("can't delete default identity", null);
/*       */     }
/*  7310 */     account.setCachedData("LdapProvisioning.IDENTITY_CACHE", null);
/*       */     
/*  7312 */     ZLdapContext zlc = null;
/*       */     try {
/*  7314 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_IDENTITY);
/*  7315 */       Identity identity = getIdentityByName(ldapEntry, identityName, zlc);
/*  7316 */       if (identity == null)
/*  7317 */         throw AccountServiceException.NO_SUCH_IDENTITY(identityName);
/*  7318 */       String dn = getIdentityDn(ldapEntry, identityName);
/*  7319 */       zlc.deleteEntry(dn);
/*       */     } catch (ServiceException e) {
/*  7321 */       throw ServiceException.FAILURE("unable to delete identity: " + identityName, e);
/*       */     } finally {
/*  7323 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public List<Identity> getAllIdentities(Account account) throws ServiceException
/*       */   {
/*  7329 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7330 */     if (ldapEntry == null) {
/*  7331 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*       */     
/*  7334 */     List<Identity> result = (List)account.getCachedData("LdapProvisioning.IDENTITY_CACHE");
/*       */     
/*  7336 */     if (result != null) {
/*  7337 */       return result;
/*       */     }
/*       */     
/*  7340 */     result = getIdentitiesByQuery(ldapEntry, this.filterFactory.allIdentities(), null);
/*  7341 */     for (Identity identity : result)
/*       */     {
/*  7343 */       if (identity.getId() == null) {
/*  7344 */         String id = LdapUtil.generateUUID();
/*  7345 */         identity.setId(id);
/*  7346 */         Map<String, Object> newAttrs = new HashMap();
/*  7347 */         newAttrs.put("zimbraPrefIdentityId", id);
/*       */         try {
/*  7349 */           modifyIdentity(account, identity.getName(), newAttrs);
/*       */         } catch (ServiceException se) {
/*  7351 */           ZimbraLog.account.warn("error updating identity: " + account.getName() + " " + identity.getName() + " " + se.getMessage(), se);
/*       */         }
/*       */       }
/*       */     }
/*  7355 */     result.add(getDefaultIdentity(account));
/*  7356 */     result = Collections.unmodifiableList(result);
/*  7357 */     account.setCachedData("LdapProvisioning.IDENTITY_CACHE", result);
/*  7358 */     return result;
/*       */   }
/*       */   
/*       */   public Identity get(Account account, Key.IdentityBy keyType, String key)
/*       */     throws ServiceException
/*       */   {
/*  7364 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7365 */     if (ldapEntry == null) {
/*  7366 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*       */     
/*       */ 
/*  7370 */     switch (keyType) {
/*       */     case id: 
/*  7372 */       for (Identity identity : getAllIdentities(account))
/*  7373 */         if (identity.getId().equals(key)) return identity;
/*  7374 */       return null;
/*       */     case name: 
/*  7376 */       for (Identity identity : getAllIdentities(account))
/*  7377 */         if (identity.getName().equalsIgnoreCase(key)) return identity;
/*  7378 */       return null;
/*       */     }
/*  7380 */     return null;
/*       */   }
/*       */   
/*       */   private List<Signature> getSignaturesByQuery(Account acct, LdapEntry entry, ZLdapFilter filter, ZLdapContext initZlc, List<Signature> result)
/*       */     throws ServiceException
/*       */   {
/*  7386 */     if (result == null) {
/*  7387 */       result = new ArrayList();
/*       */     }
/*       */     try
/*       */     {
/*  7391 */       String base = entry.getDN();
/*  7392 */       ZSearchResultEnumeration ne = this.helper.searchDir(base, filter, ZSearchControls.SEARCH_CTLS_SUBTREE(), initZlc, LdapServerType.REPLICA);
/*       */       
/*  7394 */       while (ne.hasMore()) {
/*  7395 */         ZSearchResultEntry sr = ne.next();
/*  7396 */         result.add(new LdapSignature(acct, sr.getDN(), sr.getAttributes(), this));
/*       */       }
/*  7398 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  7400 */       throw ServiceException.FAILURE("unable to lookup signature via query: " + filter.toFilterString() + " message: " + e.getMessage(), e);
/*       */     }
/*       */     
/*  7403 */     return result;
/*       */   }
/*       */   
/*       */   private Signature getSignatureById(Account acct, LdapEntry entry, String id, ZLdapContext zlc) throws ServiceException
/*       */   {
/*  7408 */     List<Signature> result = getSignaturesByQuery(acct, entry, this.filterFactory.signatureById(id), zlc, null);
/*  7409 */     return result.isEmpty() ? null : (Signature)result.get(0);
/*       */   }
/*       */   
/*       */   private String getSignatureDn(LdapEntry entry, String name) {
/*  7413 */     return "zimbraSignatureName=" + LdapUtil.escapeRDNValue(name) + "," + entry.getDN();
/*       */   }
/*       */   
/*       */   private void validateSignatureAttrs(Map<String, Object> attrs) throws ServiceException {
/*  7417 */     Set<String> validAttrs = AttributeManager.getInstance().getLowerCaseAttrsInClass(AttributeClass.signature);
/*  7418 */     for (String key : attrs.keySet()) {
/*  7419 */       if (!validAttrs.contains(key.toLowerCase())) {
/*  7420 */         throw ServiceException.INVALID_REQUEST("unable to modify attr: " + key, null);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   private void setDefaultSignature(Account acct, String signatureId) throws ServiceException {
/*  7426 */     Map<String, Object> attrs = new HashMap();
/*  7427 */     attrs.put("zimbraPrefDefaultSignatureId", signatureId);
/*  7428 */     modifyAttrs(acct, attrs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public Signature createSignature(Account account, String signatureName, Map<String, Object> signatureAttrs)
/*       */     throws ServiceException
/*       */   {
/*  7436 */     return createSignature(account, signatureName, signatureAttrs, false);
/*       */   }
/*       */   
/*       */   public Signature restoreSignature(Account account, String signatureName, Map<String, Object> signatureAttrs) throws ServiceException
/*       */   {
/*  7441 */     return createSignature(account, signatureName, signatureAttrs, true);
/*       */   }
/*       */   
/*       */   private Signature createSignature(Account account, String signatureName, Map<String, Object> signatureAttrs, boolean restoring) throws ServiceException
/*       */   {
/*  7446 */     signatureName = signatureName.trim();
/*  7447 */     removeAttrIgnoreCase("objectclass", signatureAttrs);
/*  7448 */     validateSignatureAttrs(signatureAttrs);
/*       */     
/*  7450 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*       */     
/*  7452 */     if (ldapEntry == null) {
/*  7453 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  7463 */     Signature acctSig = LdapSignature.getAccountSignature(this, account);
/*  7464 */     if ((acctSig != null) && (signatureName.equalsIgnoreCase(acctSig.getName()))) {
/*  7465 */       throw AccountServiceException.SIGNATURE_EXISTS(signatureName);
/*       */     }
/*  7467 */     boolean setAsDefault = false;
/*  7468 */     List<Signature> existing = getAllSignatures(account);
/*       */     
/*       */ 
/*       */ 
/*  7472 */     String signatureId = (String)signatureAttrs.get("zimbraSignatureId");
/*  7473 */     if (signatureId != null) {
/*  7474 */       for (Signature signature : existing) {
/*  7475 */         if (signatureId.equals(signature.getAttr("zimbraSignatureId"))) {
/*  7476 */           throw AccountServiceException.SIGNATURE_EXISTS(signatureId);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*  7482 */     int numSigs = existing.size();
/*  7483 */     if (numSigs >= account.getLongAttr("zimbraSignatureMaxNumEntries", 20L))
/*  7484 */       throw AccountServiceException.TOO_MANY_SIGNATURES();
/*  7485 */     if (numSigs == 0) {
/*  7486 */       setAsDefault = true;
/*       */     }
/*  7488 */     account.setCachedData("LdapProvisioning.SIGNATURE_CACHE", null);
/*       */     
/*  7490 */     boolean checkImmutable = !restoring;
/*  7491 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  7492 */     callbackContext.setData(CallbackContext.DataKey.MAX_SIGNATURE_LEN, String.valueOf(account.getMailSignatureMaxLength()));
/*       */     
/*  7494 */     AttributeManager.getInstance().preModify(signatureAttrs, null, callbackContext, checkImmutable);
/*       */     
/*       */ 
/*       */ 
/*  7498 */     if (signatureId == null) {
/*  7499 */       signatureId = LdapUtil.generateUUID();
/*  7500 */       signatureAttrs.put("zimbraSignatureId", signatureId);
/*       */     }
/*       */     
/*  7503 */     if (acctSig == null)
/*       */     {
/*  7505 */       signatureAttrs.put("zimbraSignatureName", signatureName);
/*       */       
/*       */ 
/*  7508 */       LdapSignature.createAccountSignature(this, account, signatureAttrs, setAsDefault);
/*  7509 */       return LdapSignature.getAccountSignature(this, account);
/*       */     }
/*       */     
/*  7512 */     ZLdapContext zlc = null;
/*       */     try {
/*  7514 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_SIGNATURE);
/*       */       
/*  7516 */       String dn = getSignatureDn(ldapEntry, signatureName);
/*       */       
/*  7518 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  7519 */       entry.mapToAttrs(signatureAttrs);
/*       */       
/*  7521 */       entry.setAttr("objectClass", "zimbraSignature");
/*  7522 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*       */       
/*  7524 */       entry.setDN(dn);
/*  7525 */       zlc.createEntry(entry);
/*       */       
/*  7527 */       Signature signature = getSignatureById(account, ldapEntry, signatureId, zlc);
/*  7528 */       AttributeManager.getInstance().postModify(signatureAttrs, signature, callbackContext);
/*       */       
/*  7530 */       if (setAsDefault) {
/*  7531 */         setDefaultSignature(account, signatureId);
/*       */       }
/*  7533 */       return signature;
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  7535 */       throw AccountServiceException.SIGNATURE_EXISTS(signatureName);
/*       */     } catch (LdapException e) {
/*  7537 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  7539 */       throw e;
/*       */     } catch (ServiceException e) {
/*  7541 */       throw ServiceException.FAILURE("unable to create signature: " + signatureName, e);
/*       */     } finally {
/*  7543 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void modifySignature(Account account, String signatureId, Map<String, Object> signatureAttrs)
/*       */     throws ServiceException
/*       */   {
/*  7550 */     removeAttrIgnoreCase("objectclass", signatureAttrs);
/*       */     
/*  7552 */     validateSignatureAttrs(signatureAttrs);
/*       */     
/*  7554 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*       */     
/*  7556 */     if (ldapEntry == null) {
/*  7557 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*  7559 */     String newName = (String)signatureAttrs.get("zimbraSignatureName");
/*       */     
/*  7561 */     if (newName != null) {
/*  7562 */       newName = newName.trim();
/*       */       
/*       */ 
/*  7565 */       if (newName.length() == 0) {
/*  7566 */         throw ServiceException.INVALID_REQUEST("empty signature name is not allowed", null);
/*       */       }
/*       */       
/*  7569 */       List<Signature> sigs = getAllSignatures(account);
/*  7570 */       for (Signature sig : sigs) {
/*  7571 */         if ((sig.getName().equalsIgnoreCase(newName)) && (!sig.getId().equals(signatureId))) {
/*  7572 */           throw AccountServiceException.SIGNATURE_EXISTS(newName);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*  7577 */     account.setCachedData("LdapProvisioning.SIGNATURE_CACHE", null);
/*       */     
/*  7579 */     if (LdapSignature.isAccountSignature(account, signatureId)) {
/*  7580 */       LdapSignature.modifyAccountSignature(this, account, signatureAttrs);
/*       */     }
/*       */     else {
/*  7583 */       LdapSignature signature = (LdapSignature)getSignatureById(account, ldapEntry, signatureId, null);
/*  7584 */       if (signature == null) {
/*  7585 */         throw AccountServiceException.NO_SUCH_SIGNATURE(signatureId);
/*       */       }
/*  7587 */       boolean nameChanged = (newName != null) && (!newName.equals(signature.getName()));
/*       */       
/*  7589 */       if (nameChanged) {
/*  7590 */         signatureAttrs.remove("zimbraSignatureName");
/*       */       }
/*  7592 */       modifyAttrs(signature, signatureAttrs, true);
/*  7593 */       if (nameChanged)
/*       */       {
/*       */ 
/*  7596 */         account.setCachedData("LdapProvisioning.SIGNATURE_CACHE", null);
/*  7597 */         renameSignature(ldapEntry, signature, newName);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   private void renameSignature(LdapEntry entry, LdapSignature signature, String newSignatureName)
/*       */     throws ServiceException
/*       */   {
/*  7605 */     ZLdapContext zlc = null;
/*       */     try {
/*  7607 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_SIGNATURE);
/*  7608 */       String newDn = getSignatureDn(entry, newSignatureName);
/*  7609 */       zlc.renameEntry(signature.getDN(), newDn);
/*       */     } catch (ServiceException e) {
/*  7611 */       throw ServiceException.FAILURE("unable to rename signature: " + newSignatureName, e);
/*       */     } finally {
/*  7613 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteSignature(Account account, String signatureId) throws ServiceException
/*       */   {
/*  7619 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7620 */     if (ldapEntry == null) {
/*  7621 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*  7623 */     account.setCachedData("LdapProvisioning.SIGNATURE_CACHE", null);
/*       */     
/*  7625 */     if (LdapSignature.isAccountSignature(account, signatureId)) {
/*  7626 */       LdapSignature.deleteAccountSignature(this, account);
/*       */     } else {
/*  7628 */       ZLdapContext zlc = null;
/*       */       try {
/*  7630 */         zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_SIGNATURE);
/*  7631 */         Signature signature = getSignatureById(account, ldapEntry, signatureId, zlc);
/*  7632 */         if (signature == null)
/*  7633 */           throw AccountServiceException.NO_SUCH_SIGNATURE(signatureId);
/*  7634 */         String dn = getSignatureDn(ldapEntry, signature.getName());
/*  7635 */         zlc.deleteEntry(dn);
/*       */       } catch (ServiceException e) {
/*  7637 */         throw ServiceException.FAILURE("unable to delete signarure: " + signatureId, e);
/*       */       } finally {
/*  7639 */         LdapClient.closeContext(zlc);
/*       */       }
/*       */     }
/*       */     
/*  7643 */     if (signatureId.equals(account.getPrefDefaultSignatureId())) {
/*  7644 */       account.unsetPrefDefaultSignatureId();
/*       */     }
/*       */   }
/*       */   
/*       */   public List<Signature> getAllSignatures(Account account) throws ServiceException
/*       */   {
/*  7650 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7651 */     if (ldapEntry == null) {
/*  7652 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*       */     
/*  7655 */     List<Signature> result = (List)account.getCachedData("LdapProvisioning.SIGNATURE_CACHE");
/*       */     
/*  7657 */     if (result != null) {
/*  7658 */       return result;
/*       */     }
/*       */     
/*  7661 */     result = new ArrayList();
/*  7662 */     Signature acctSig = LdapSignature.getAccountSignature(this, account);
/*  7663 */     if (acctSig != null) {
/*  7664 */       result.add(acctSig);
/*       */     }
/*  7666 */     result = getSignaturesByQuery(account, ldapEntry, this.filterFactory.allSignatures(), null, result);
/*       */     
/*  7668 */     result = Collections.unmodifiableList(result);
/*  7669 */     account.setCachedData("LdapProvisioning.SIGNATURE_CACHE", result);
/*  7670 */     return result;
/*       */   }
/*       */   
/*       */   public Signature get(Account account, Key.SignatureBy keyType, String key)
/*       */     throws ServiceException
/*       */   {
/*  7676 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7677 */     if (ldapEntry == null) {
/*  7678 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*       */     
/*       */ 
/*  7682 */     switch (keyType) {
/*       */     case id: 
/*  7684 */       for (Signature signature : getAllSignatures(account))
/*  7685 */         if (signature.getId().equals(key)) return signature;
/*  7686 */       return null;
/*       */     case name: 
/*  7688 */       for (Signature signature : getAllSignatures(account))
/*  7689 */         if (signature.getName().equalsIgnoreCase(key)) return signature;
/*  7690 */       return null;
/*       */     }
/*  7692 */     return null;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   private List<DataSource> getDataSourcesByQuery(LdapEntry entry, ZLdapFilter filter, ZLdapContext initZlc)
/*       */     throws ServiceException
/*       */   {
/*  7700 */     List<DataSource> result = new ArrayList();
/*       */     try
/*       */     {
/*  7703 */       String base = entry.getDN();
/*  7704 */       ZSearchResultEnumeration ne = this.helper.searchDir(base, filter, ZSearchControls.SEARCH_CTLS_SUBTREE(), initZlc, LdapServerType.REPLICA);
/*       */       
/*  7706 */       while (ne.hasMore()) {
/*  7707 */         ZSearchResultEntry sr = ne.next();
/*  7708 */         result.add(new LdapDataSource((Account)entry, sr.getDN(), sr.getAttributes(), this));
/*       */       }
/*  7710 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  7712 */       throw ServiceException.FAILURE("unable to lookup data source via query: " + filter.toFilterString() + " message: " + e.getMessage(), e);
/*       */     }
/*       */     
/*  7715 */     return result;
/*       */   }
/*       */   
/*       */   private DataSource getDataSourceById(LdapEntry entry, String id, ZLdapContext zlc) throws ServiceException
/*       */   {
/*  7720 */     List<DataSource> result = getDataSourcesByQuery(entry, this.filterFactory.dataSourceById(id), zlc);
/*  7721 */     return result.isEmpty() ? null : (DataSource)result.get(0);
/*       */   }
/*       */   
/*       */   private String getDataSourceDn(LdapEntry entry, String name) {
/*  7725 */     return "zimbraDataSourceName=" + LdapUtil.escapeRDNValue(name) + "," + entry.getDN();
/*       */   }
/*       */   
/*       */   protected ReplaceAddressResult replaceMailAddresses(Entry entry, String attrName, String oldAddr, String newAddr)
/*       */     throws ServiceException
/*       */   {
/*  7731 */     String oldDomain = EmailUtil.getValidDomainPart(oldAddr);
/*  7732 */     String newDomain = EmailUtil.getValidDomainPart(newAddr);
/*       */     
/*  7734 */     String[] oldAddrs = entry.getMultiAttr(attrName);
/*  7735 */     String[] newAddrs = new String[0];
/*       */     
/*  7737 */     for (int i = 0; i < oldAddrs.length; i++) {
/*  7738 */       String oldMail = oldAddrs[i];
/*  7739 */       if (oldMail.equals(oldAddr))
/*       */       {
/*  7741 */         newAddrs = addMultiValue(newAddrs, newAddr);
/*       */       } else {
/*  7743 */         String[] oldParts = EmailUtil.getLocalPartAndDomain(oldMail);
/*       */         
/*       */ 
/*  7746 */         if (oldParts == null)
/*  7747 */           throw ServiceException.FAILURE("bad value for " + attrName + " " + oldMail, null);
/*  7748 */         String oldL = oldParts[0];
/*  7749 */         String oldD = oldParts[1];
/*       */         
/*  7751 */         if (oldD.equals(oldDomain))
/*       */         {
/*       */ 
/*       */ 
/*  7755 */           String newMail = oldL + "@" + newDomain;
/*  7756 */           newAddrs = addMultiValue(newAddrs, newMail);
/*       */         }
/*       */         else {
/*  7759 */           newAddrs = addMultiValue(newAddrs, oldMail);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*  7765 */     return new ReplaceAddressResult(oldAddrs, newAddrs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void moveAliases(ZLdapContext zlc, ReplaceAddressResult addrs, String newDomain, String primaryUid, String targetOldDn, String targetNewDn, String targetOldDomain, String targetNewDomain)
/*       */     throws ServiceException
/*       */   {
/*  7778 */     for (int i = 0; i < addrs.newAddrs().length; i++) {
/*  7779 */       String oldAddr = addrs.oldAddrs()[i];
/*  7780 */       String newAddr = addrs.newAddrs()[i];
/*       */       
/*  7782 */       String aliasNewDomain = EmailUtil.getValidDomainPart(newAddr);
/*       */       
/*  7784 */       if (aliasNewDomain.equals(newDomain)) {
/*  7785 */         String[] oldParts = EmailUtil.getLocalPartAndDomain(oldAddr);
/*  7786 */         String oldAliasDN = this.mDIT.aliasDN(targetOldDn, targetOldDomain, oldParts[0], oldParts[1]);
/*  7787 */         String newAliasDN = this.mDIT.aliasDNRename(targetNewDn, targetNewDomain, newAddr);
/*       */         
/*  7789 */         if (!oldAliasDN.equals(newAliasDN))
/*       */         {
/*       */ 
/*       */ 
/*  7793 */           String[] newAliasParts = EmailUtil.getLocalPartAndDomain(newAddr);
/*  7794 */           String newAliasLocal = newAliasParts[0];
/*  7795 */           if ((primaryUid == null) || (!newAliasLocal.equals(primaryUid))) {
/*       */             try {
/*  7797 */               zlc.renameEntry(oldAliasDN, newAliasDN);
/*  7798 */             } catch (LdapException.LdapEntryAlreadyExistException nabe) { nabe = 
/*       */               
/*       */ 
/*       */ 
/*       */ 
/*  7803 */                 nabe;ZimbraLog.account.warn("unable to move alias from " + oldAliasDN + " to " + newAliasDN, nabe);
/*       */             }
/*       */             catch (ServiceException ne)
/*       */             {
/*  7800 */               ne = 
/*       */               
/*       */ 
/*  7803 */                 ne;throw ServiceException.FAILURE("unable to move aliases", null);
/*       */             }
/*       */             finally {}
/*       */           }
/*       */         }
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   public DataSource createDataSource(Account account, DataSourceType dsType, String dsName, Map<String, Object> dataSourceAttrs) throws ServiceException
/*       */   {
/*  7814 */     return createDataSource(account, dsType, dsName, dataSourceAttrs, false);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public DataSource createDataSource(Account account, DataSourceType type, String dataSourceName, Map<String, Object> attrs, boolean passwdAlreadyEncrypted)
/*       */     throws ServiceException
/*       */   {
/*  7822 */     return createDataSource(account, type, dataSourceName, attrs, passwdAlreadyEncrypted, false);
/*       */   }
/*       */   
/*       */ 
/*       */   public DataSource restoreDataSource(Account account, DataSourceType dsType, String dsName, Map<String, Object> dataSourceAttrs)
/*       */     throws ServiceException
/*       */   {
/*  7829 */     return createDataSource(account, dsType, dsName, dataSourceAttrs, true, true);
/*       */   }
/*       */   
/*       */ 
/*       */   private DataSource createDataSource(Account account, DataSourceType dsType, String dsName, Map<String, Object> dataSourceAttrs, boolean passwdAlreadyEncrypted, boolean restoring)
/*       */     throws ServiceException
/*       */   {
/*  7836 */     removeAttrIgnoreCase("objectclass", dataSourceAttrs);
/*  7837 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*       */     
/*  7839 */     if (ldapEntry == null) {
/*  7840 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*  7842 */     List<DataSource> existing = getAllDataSources(account);
/*  7843 */     if (existing.size() >= account.getLongAttr("zimbraDataSourceMaxNumEntries", 20L)) {
/*  7844 */       throw AccountServiceException.TOO_MANY_DATA_SOURCES();
/*       */     }
/*  7846 */     dataSourceAttrs.put("zimbraDataSourceName", dsName);
/*  7847 */     dataSourceAttrs.put("zimbraDataSourceType", dsType.toString());
/*       */     
/*  7849 */     account.setCachedData("LdapProvisioning.DATA_SOURCE_CACHE", null);
/*       */     
/*  7851 */     boolean checkImmutable = !restoring;
/*  7852 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  7853 */     AttributeManager.getInstance().preModify(dataSourceAttrs, null, callbackContext, checkImmutable);
/*       */     
/*  7855 */     ZLdapContext zlc = null;
/*       */     try {
/*  7857 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_DATASOURCE);
/*       */       
/*  7859 */       String dn = getDataSourceDn(ldapEntry, dsName);
/*       */       
/*  7861 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  7862 */       entry.setDN(dn);
/*  7863 */       entry.mapToAttrs(dataSourceAttrs);
/*       */       
/*  7865 */       entry.setAttr("objectClass", "zimbraDataSource");
/*  7866 */       String extraOc = LdapDataSource.getObjectClass(dsType);
/*  7867 */       if (extraOc != null) {
/*  7868 */         entry.addAttr("objectClass", Sets.newHashSet(new String[] { extraOc }));
/*       */       }
/*       */       
/*  7871 */       String dsId = entry.getAttrString("zimbraDataSourceId");
/*  7872 */       if (dsId == null) {
/*  7873 */         dsId = LdapUtil.generateUUID();
/*  7874 */         entry.setAttr("zimbraDataSourceId", dsId);
/*       */       }
/*       */       
/*  7877 */       String password = entry.getAttrString("zimbraDataSourcePassword");
/*  7878 */       if (password != null) {
/*  7879 */         String encrypted = passwdAlreadyEncrypted ? password : DataSource.encryptData(dsId, password);
/*  7880 */         entry.setAttr("zimbraDataSourcePassword", encrypted);
/*       */       }
/*  7882 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*       */       
/*  7884 */       zlc.createEntry(entry);
/*       */       
/*  7886 */       DataSource ds = getDataSourceById(ldapEntry, dsId, zlc);
/*  7887 */       AttributeManager.getInstance().postModify(dataSourceAttrs, ds, callbackContext);
/*  7888 */       return ds;
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  7890 */       throw AccountServiceException.DATA_SOURCE_EXISTS(dsName);
/*       */     } catch (LdapException e) {
/*  7892 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  7894 */       throw e;
/*       */     } catch (ServiceException e) {
/*  7896 */       throw ServiceException.FAILURE("unable to create data source: " + dsName, e);
/*       */     } finally {
/*  7898 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteDataSource(Account account, String dataSourceId) throws ServiceException
/*       */   {
/*  7904 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7905 */     if (ldapEntry == null) {
/*  7906 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*  7908 */     account.setCachedData("LdapProvisioning.DATA_SOURCE_CACHE", null);
/*       */     
/*  7910 */     ZLdapContext zlc = null;
/*       */     try {
/*  7912 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_DATASOURCE);
/*  7913 */       DataSource dataSource = getDataSourceById(ldapEntry, dataSourceId, zlc);
/*  7914 */       if (dataSource == null)
/*  7915 */         throw AccountServiceException.NO_SUCH_DATA_SOURCE(dataSourceId);
/*  7916 */       String dn = getDataSourceDn(ldapEntry, dataSource.getName());
/*  7917 */       zlc.deleteEntry(dn);
/*       */     } catch (ServiceException e) {
/*  7919 */       throw ServiceException.FAILURE("unable to delete data source: " + dataSourceId, e);
/*       */     } finally {
/*  7921 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public List<DataSource> getAllDataSources(Account account)
/*       */     throws ServiceException
/*       */   {
/*  7930 */     List<DataSource> result = (List)account.getCachedData("LdapProvisioning.DATA_SOURCE_CACHE");
/*       */     
/*  7932 */     if (result != null) {
/*  7933 */       return result;
/*       */     }
/*       */     
/*  7936 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7937 */     if (ldapEntry == null)
/*  7938 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*  7939 */     result = getDataSourcesByQuery(ldapEntry, this.filterFactory.allDataSources(), null);
/*  7940 */     result = Collections.unmodifiableList(result);
/*  7941 */     account.setCachedData("LdapProvisioning.DATA_SOURCE_CACHE", result);
/*  7942 */     return result;
/*       */   }
/*       */   
/*       */   public void removeAttrIgnoreCase(String attr, Map<String, Object> attrs) {
/*  7946 */     for (String key : attrs.keySet()) {
/*  7947 */       if (key.equalsIgnoreCase(attr)) {
/*  7948 */         attrs.remove(key);
/*  7949 */         return;
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   public void modifyDataSource(Account account, String dataSourceId, Map<String, Object> attrs)
/*       */     throws ServiceException
/*       */   {
/*  7957 */     removeAttrIgnoreCase("objectclass", attrs);
/*  7958 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  7959 */     if (ldapEntry == null) {
/*  7960 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*  7962 */     LdapDataSource ds = (LdapDataSource)getDataSourceById(ldapEntry, dataSourceId, null);
/*  7963 */     if (ds == null) {
/*  7964 */       throw AccountServiceException.NO_SUCH_DATA_SOURCE(dataSourceId);
/*       */     }
/*  7966 */     account.setCachedData("LdapProvisioning.DATA_SOURCE_CACHE", null);
/*       */     
/*  7968 */     attrs.remove("zimbraDataSourceId");
/*       */     
/*  7970 */     String name = (String)attrs.get("zimbraDataSourceName");
/*  7971 */     boolean newName = (name != null) && (!name.equals(ds.getName()));
/*  7972 */     if (newName) { attrs.remove("zimbraDataSourceName");
/*       */     }
/*  7974 */     String password = (String)attrs.get("zimbraDataSourcePassword");
/*  7975 */     if (password != null) {
/*  7976 */       attrs.put("zimbraDataSourcePassword", DataSource.encryptData(ds.getId(), password));
/*       */     }
/*       */     
/*       */ 
/*  7980 */     modifyAttrs(ds, attrs, true);
/*  7981 */     if (newName)
/*       */     {
/*  7983 */       account.setCachedData("LdapProvisioning.DATA_SOURCE_CACHE", null);
/*  7984 */       ZLdapContext zlc = null;
/*       */       try {
/*  7986 */         zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_DATASOURCE);
/*  7987 */         String newDn = getDataSourceDn(ldapEntry, name);
/*  7988 */         zlc.renameEntry(ds.getDN(), newDn);
/*       */       } catch (ServiceException e) {
/*  7990 */         throw ServiceException.FAILURE("unable to rename datasource: " + name, e);
/*       */       } finally {
/*  7992 */         LdapClient.closeContext(zlc);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   public DataSource get(Account account, Key.DataSourceBy keyType, String key)
/*       */     throws ServiceException
/*       */   {
/*  8000 */     LdapEntry ldapEntry = (LdapEntry)((account instanceof LdapEntry) ? account : getAccountById(account.getId()));
/*  8001 */     if (ldapEntry == null) {
/*  8002 */       throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*  8007 */     switch (keyType) {
/*       */     case id: 
/*  8009 */       for (DataSource source : getAllDataSources(account))
/*  8010 */         if (source.getId().equals(key))
/*  8011 */           return source;
/*  8012 */       return null;
/*       */     
/*       */     case name: 
/*  8015 */       for (DataSource source : getAllDataSources(account))
/*  8016 */         if (source.getName().equalsIgnoreCase(key))
/*  8017 */           return source;
/*  8018 */       return null;
/*       */     }
/*       */     
/*  8021 */     return null;
/*       */   }
/*       */   
/*       */   private XMPPComponent getXMPPComponentByQuery(ZLdapFilter filter, ZLdapContext initZlc) throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*  8028 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.xmppcomponentBaseDN(), filter, initZlc, false);
/*  8029 */       if (sr != null) {
/*  8030 */         return new LdapXMPPComponent(sr.getDN(), sr.getAttributes(), this);
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  8033 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getXMPPComponentByQuery", e);
/*       */     } catch (ServiceException e) {
/*  8035 */       throw ServiceException.FAILURE("unable to lookup XMPP component via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  8038 */     return null;
/*       */   }
/*       */   
/*       */   private XMPPComponent getXMPPComponentByName(String name, boolean nocache) throws ServiceException
/*       */   {
/*  8043 */     if (!nocache) {
/*  8044 */       XMPPComponent x = (XMPPComponent)this.xmppComponentCache.getByName(name);
/*  8045 */       if (x != null) {
/*  8046 */         return x;
/*       */       }
/*       */     }
/*       */     try {
/*  8050 */       String dn = this.mDIT.xmppcomponentNameToDN(name);
/*  8051 */       ZAttributes attrs = this.helper.getAttributes(LdapUsage.GET_XMPPCOMPONENT, dn);
/*  8052 */       XMPPComponent x = new LdapXMPPComponent(dn, attrs, this);
/*  8053 */       this.xmppComponentCache.put(x);
/*  8054 */       return x;
/*       */     } catch (LdapException.LdapEntryNotFoundException e) {
/*  8056 */       return null;
/*       */     } catch (ServiceException e) {
/*  8058 */       throw ServiceException.FAILURE("unable to lookup xmpp component by name: " + name + " message: " + e.getMessage(), e);
/*       */     }
/*       */   }
/*       */   
/*       */   private XMPPComponent getXMPPComponentById(String zimbraId, ZLdapContext zlc, boolean nocache) throws ServiceException
/*       */   {
/*  8064 */     if (zimbraId == null)
/*  8065 */       return null;
/*  8066 */     XMPPComponent x = null;
/*  8067 */     if (!nocache)
/*  8068 */       x = (XMPPComponent)this.xmppComponentCache.getById(zimbraId);
/*  8069 */     if (x == null) {
/*  8070 */       x = getXMPPComponentByQuery(this.filterFactory.xmppComponentById(zimbraId), zlc);
/*  8071 */       this.xmppComponentCache.put(x);
/*       */     }
/*  8073 */     return x;
/*       */   }
/*       */   
/*       */   public List<XMPPComponent> getAllXMPPComponents() throws ServiceException
/*       */   {
/*  8078 */     List<XMPPComponent> result = new ArrayList();
/*       */     try
/*       */     {
/*  8081 */       String base = this.mDIT.xmppcomponentBaseDN();
/*  8082 */       ZLdapFilter filter = this.filterFactory.allXMPPComponents();
/*       */       
/*  8084 */       ZSearchResultEnumeration ne = this.helper.searchDir(base, filter, ZSearchControls.SEARCH_CTLS_SUBTREE());
/*  8085 */       while (ne.hasMore()) {
/*  8086 */         ZSearchResultEntry sr = ne.next();
/*  8087 */         LdapXMPPComponent x = new LdapXMPPComponent(sr.getDN(), sr.getAttributes(), this);
/*  8088 */         result.add(x);
/*       */       }
/*  8090 */       ne.close();
/*       */     } catch (ServiceException e) {
/*  8092 */       throw ServiceException.FAILURE("unable to list all XMPPComponents", e);
/*       */     }
/*       */     
/*  8095 */     if (result.size() > 0) {
/*  8096 */       this.xmppComponentCache.put(result, true);
/*       */     }
/*  8098 */     Collections.sort(result);
/*  8099 */     return result;
/*       */   }
/*       */   
/*       */ 
/*       */   public XMPPComponent createXMPPComponent(String name, Domain domain, Server server, Map<String, Object> inAttrs)
/*       */     throws ServiceException
/*       */   {
/*  8106 */     name = name.toLowerCase().trim();
/*       */     
/*       */ 
/*  8109 */     removeAttrIgnoreCase("objectclass", inAttrs);
/*  8110 */     removeAttrIgnoreCase("zimbraDomainId", inAttrs);
/*  8111 */     removeAttrIgnoreCase("zimbraServerId", inAttrs);
/*       */     
/*  8113 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  8114 */     AttributeManager.getInstance().preModify(inAttrs, null, callbackContext, true);
/*       */     
/*  8116 */     ZLdapContext zlc = null;
/*       */     try {
/*  8118 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_XMPPCOMPONENT);
/*       */       
/*  8120 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  8121 */       entry.mapToAttrs(inAttrs);
/*       */       
/*  8123 */       entry.setAttr("objectClass", "zimbraXMPPComponent");
/*       */       
/*  8125 */       String compId = LdapUtil.generateUUID();
/*  8126 */       entry.setAttr("zimbraId", compId);
/*  8127 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/*  8128 */       entry.setAttr("cn", name);
/*  8129 */       String dn = this.mDIT.xmppcomponentNameToDN(name);
/*  8130 */       entry.setDN(dn);
/*       */       
/*  8132 */       entry.setAttr("zimbraDomainId", domain.getId());
/*  8133 */       entry.setAttr("zimbraServerId", server.getId());
/*       */       
/*  8135 */       zlc.createEntry(entry);
/*       */       
/*  8137 */       XMPPComponent comp = getXMPPComponentById(compId, zlc, true);
/*  8138 */       AttributeManager.getInstance().postModify(inAttrs, comp, callbackContext);
/*  8139 */       return comp;
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  8141 */       throw AccountServiceException.IM_COMPONENT_EXISTS(name);
/*       */     } finally {
/*  8143 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public XMPPComponent get(Key.XMPPComponentBy keyType, String key) throws ServiceException
/*       */   {
/*  8149 */     switch (keyType) {
/*       */     case name: 
/*  8151 */       return getXMPPComponentByName(key, false);
/*       */     case id: 
/*  8153 */       return getXMPPComponentById(key, null, false);
/*       */     case serviceHostname: 
/*  8155 */       throw new UnsupportedOperationException("Writeme!");
/*       */     }
/*       */     
/*  8158 */     return null;
/*       */   }
/*       */   
/*       */   public void deleteXMPPComponent(XMPPComponent comp) throws ServiceException
/*       */   {
/*  8163 */     String zimbraId = comp.getId();
/*  8164 */     ZLdapContext zlc = null;
/*  8165 */     LdapXMPPComponent l = (LdapXMPPComponent)get(Key.XMPPComponentBy.id, zimbraId);
/*       */     try {
/*  8167 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_XMPPCOMPONENT);
/*  8168 */       zlc.deleteEntry(l.getDN());
/*  8169 */       this.xmppComponentCache.remove(l);
/*       */     } catch (ServiceException e) {
/*  8171 */       throw ServiceException.FAILURE("unable to purge XMPPComponent : " + zimbraId, e);
/*       */     } finally {
/*  8173 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   void renameXMPPComponent(String zimbraId, String newName) throws ServiceException
/*       */   {
/*  8179 */     LdapXMPPComponent comp = (LdapXMPPComponent)get(Key.XMPPComponentBy.id, zimbraId);
/*  8180 */     if (comp == null) {
/*  8181 */       throw AccountServiceException.NO_SUCH_XMPP_COMPONENT(zimbraId);
/*       */     }
/*  8183 */     newName = newName.toLowerCase().trim();
/*  8184 */     ZLdapContext zlc = null;
/*       */     try {
/*  8186 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_XMPPCOMPONENT);
/*  8187 */       String newDn = this.mDIT.xmppcomponentNameToDN(newName);
/*  8188 */       zlc.renameEntry(comp.getDN(), newDn);
/*       */       
/*  8190 */       this.xmppComponentCache.remove(comp);
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  8192 */       throw AccountServiceException.IM_COMPONENT_EXISTS(newName);
/*       */     } catch (LdapException e) {
/*  8194 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  8196 */       throw e;
/*       */     } catch (ServiceException e) {
/*  8198 */       throw ServiceException.FAILURE("unable to rename XMPPComponent: " + zimbraId, e);
/*       */     } finally {
/*  8200 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public Right getRight(String rightName, boolean expandAllAttrs)
/*       */     throws ServiceException
/*       */   {
/*  8214 */     if (expandAllAttrs)
/*  8215 */       throw ServiceException.FAILURE("expandAllAttrs is not supported", null);
/*  8216 */     return RightCommand.getRight(rightName);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   public List<Right> getAllRights(String targetType, boolean expandAllAttrs, String rightClass)
/*       */     throws ServiceException
/*       */   {
/*  8225 */     if (expandAllAttrs)
/*  8226 */       throw ServiceException.FAILURE("expandAllAttrs == TRUE is not supported", null);
/*  8227 */     return RightCommand.getAllRights(targetType, rightClass);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public boolean checkRight(String targetType, TargetBy targetBy, String target, GranteeSelector.GranteeBy granteeBy, String granteeVal, String right, Map<String, Object> attrs, AccessManager.ViaGrant via)
/*       */     throws ServiceException
/*       */   {
/*  8235 */     MailTarget grantee = null;
/*       */     try
/*       */     {
/*  8238 */       NamedEntry ne = GranteeType.lookupGrantee(this, GranteeType.GT_EMAIL, granteeBy, granteeVal);
/*  8239 */       if ((ne instanceof MailTarget)) {
/*  8240 */         grantee = (MailTarget)ne;
/*       */       }
/*       */     }
/*       */     catch (ServiceException e) {}
/*  8244 */     if (grantee == null) {
/*  8245 */       grantee = new GuestAccount(granteeVal, null);
/*       */     }
/*       */     
/*  8248 */     return RightCommand.checkRight(this, targetType, targetBy, target, grantee, right, attrs, via);
/*       */   }
/*       */   
/*       */ 
/*       */   public com.zimbra.cs.account.accesscontrol.RightCommand.AllEffectiveRights getAllEffectiveRights(String granteeType, GranteeSelector.GranteeBy granteeBy, String grantee, boolean expandSetAttrs, boolean expandGetAttrs)
/*       */     throws ServiceException
/*       */   {
/*  8255 */     return RightCommand.getAllEffectiveRights(this, granteeType, granteeBy, grantee, expandSetAttrs, expandGetAttrs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public RightCommand.EffectiveRights getEffectiveRights(String targetType, TargetBy targetBy, String target, GranteeSelector.GranteeBy granteeBy, String grantee, boolean expandSetAttrs, boolean expandGetAttrs)
/*       */     throws ServiceException
/*       */   {
/*  8265 */     return RightCommand.getEffectiveRights(this, targetType, targetBy, target, granteeBy, grantee, expandSetAttrs, expandGetAttrs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public RightCommand.EffectiveRights getCreateObjectAttrs(String targetType, Key.DomainBy domainBy, String domainStr, Key.CosBy cosBy, String cosStr, GranteeSelector.GranteeBy granteeBy, String grantee)
/*       */     throws ServiceException
/*       */   {
/*  8277 */     return RightCommand.getCreateObjectAttrs(this, targetType, domainBy, domainStr, cosBy, cosStr, granteeBy, grantee);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public com.zimbra.cs.account.accesscontrol.RightCommand.Grants getGrants(String targetType, TargetBy targetBy, String target, String granteeType, GranteeSelector.GranteeBy granteeBy, String grantee, boolean granteeIncludeGroupsGranteeBelongs)
/*       */     throws ServiceException
/*       */   {
/*  8289 */     return RightCommand.getGrants(this, targetType, targetBy, target, granteeType, granteeBy, grantee, granteeIncludeGroupsGranteeBelongs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   public void grantRight(String targetType, TargetBy targetBy, String target, String granteeType, GranteeSelector.GranteeBy granteeBy, String grantee, String secret, String right, RightModifier rightModifier)
/*       */     throws ServiceException
/*       */   {
/*  8298 */     RightCommand.grantRight(this, null, targetType, targetBy, target, granteeType, granteeBy, grantee, secret, right, rightModifier);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public void revokeRight(String targetType, TargetBy targetBy, String target, String granteeType, GranteeSelector.GranteeBy granteeBy, String grantee, String right, RightModifier rightModifier)
/*       */     throws ServiceException
/*       */   {
/*  8310 */     RightCommand.revokeRight(this, null, targetType, targetBy, target, granteeType, granteeBy, grantee, right, rightModifier);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public void flushCache(CacheEntryType type, Provisioning.CacheEntry[] entries)
/*       */     throws ServiceException
/*       */   {
/*  8320 */     switch (type) {
/*       */     case all: 
/*  8322 */       if (entries != null) {
/*  8323 */         throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing all", null);
/*       */       }
/*  8325 */       ZimbraLog.account.info("Flushing all LDAP entry caches");
/*  8326 */       flushCache(CacheEntryType.account, null);
/*  8327 */       flushCache(CacheEntryType.group, null);
/*  8328 */       flushCache(CacheEntryType.config, null);
/*  8329 */       flushCache(CacheEntryType.globalgrant, null);
/*  8330 */       flushCache(CacheEntryType.cos, null);
/*  8331 */       flushCache(CacheEntryType.domain, null);
/*  8332 */       flushCache(CacheEntryType.mime, null);
/*  8333 */       flushCache(CacheEntryType.server, null);
/*  8334 */       flushCache(CacheEntryType.alwaysOnCluster, null);
/*  8335 */       flushCache(CacheEntryType.zimlet, null);
/*  8336 */       break;
/*       */     case account: 
/*  8338 */       if (entries != null) {
/*  8339 */         for (Provisioning.CacheEntry entry : entries) {
/*  8340 */           Key.AccountBy accountBy = entry.mEntryBy == Key.CacheEntryBy.id ? Key.AccountBy.id : Key.AccountBy.name;
/*  8341 */           Account account = getFromCache(accountBy, entry.mEntryIdentity);
/*       */           
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  8362 */           if (account != null) {
/*  8363 */             removeFromCache(account);
/*       */           }
/*       */         }
/*       */       } else {
/*  8367 */         this.accountCache.clear();
/*       */       }
/*  8369 */       return;
/*       */     case group: 
/*  8371 */       if (entries != null) {
/*  8372 */         for (Provisioning.CacheEntry entry : entries) {
/*  8373 */           Key.DistributionListBy dlBy = entry.mEntryBy == Key.CacheEntryBy.id ? Key.DistributionListBy.id : Key.DistributionListBy.name;
/*       */           
/*  8375 */           removeGroupFromCache(dlBy, entry.mEntryIdentity);
/*       */         }
/*       */       } else {
/*  8378 */         this.allDLs.clear();
/*  8379 */         this.groupCache.clear();
/*       */       }
/*  8381 */       return;
/*       */     case config: 
/*  8383 */       if (entries != null) {
/*  8384 */         throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing global config", null);
/*       */       }
/*  8386 */       Config config = getConfig();
/*  8387 */       reload(config, false);
/*  8388 */       return;
/*       */     case globalgrant: 
/*  8390 */       if (entries != null) {
/*  8391 */         throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing global grant", null);
/*       */       }
/*  8393 */       GlobalGrant globalGrant = getGlobalGrant();
/*  8394 */       reload(globalGrant, false);
/*  8395 */       return;
/*       */     case cos: 
/*  8397 */       if (entries != null) {
/*  8398 */         for (Provisioning.CacheEntry entry : entries) {
/*  8399 */           Key.CosBy cosBy = entry.mEntryBy == Key.CacheEntryBy.id ? Key.CosBy.id : Key.CosBy.name;
/*  8400 */           Cos cos = getFromCache(cosBy, entry.mEntryIdentity);
/*  8401 */           if (cos != null)
/*  8402 */             reload(cos, false);
/*       */         }
/*       */       } else
/*  8405 */         this.cosCache.clear();
/*  8406 */       return;
/*       */     case domain: 
/*  8408 */       if (entries != null) {
/*  8409 */         for (Provisioning.CacheEntry entry : entries) {
/*  8410 */           Key.DomainBy domainBy = entry.mEntryBy == Key.CacheEntryBy.id ? Key.DomainBy.id : Key.DomainBy.name;
/*  8411 */           Domain domain = getFromCache(domainBy, entry.mEntryIdentity, DomainCache.GetFromDomainCacheOption.BOTH);
/*  8412 */           if (domain != null) {
/*  8413 */             if ((domain instanceof DomainCache.NonExistingDomain)) {
/*  8414 */               this.domainCache.removeFromNegativeCache(domainBy, entry.mEntryIdentity);
/*       */             } else
/*  8416 */               reload(domain, false);
/*       */           }
/*       */         }
/*       */       } else
/*  8420 */         this.domainCache.clear();
/*  8421 */       return;
/*       */     case mime: 
/*  8423 */       this.mimeTypeCache.flushCache(this);
/*  8424 */       return;
/*       */     case server: 
/*  8426 */       if (entries != null) {
/*  8427 */         for (Provisioning.CacheEntry entry : entries) {
/*  8428 */           Key.ServerBy serverBy = entry.mEntryBy == Key.CacheEntryBy.id ? Key.ServerBy.id : Key.ServerBy.name;
/*  8429 */           Server server = get(serverBy, entry.mEntryIdentity);
/*  8430 */           if (server != null)
/*  8431 */             reload(server, false);
/*       */         }
/*       */       } else
/*  8434 */         this.serverCache.clear();
/*  8435 */       return;
/*       */     case alwaysOnCluster: 
/*  8437 */       if (entries != null) {
/*  8438 */         for (Provisioning.CacheEntry entry : entries) {
/*  8439 */           Key.AlwaysOnClusterBy clusterBy = Key.AlwaysOnClusterBy.id;
/*  8440 */           AlwaysOnCluster cluster = get(clusterBy, entry.mEntryIdentity);
/*  8441 */           if (cluster != null)
/*  8442 */             reload(cluster, false);
/*       */         }
/*       */       } else
/*  8445 */         this.alwaysOnClusterCache.clear();
/*  8446 */       return;
/*       */     case zimlet: 
/*  8448 */       if (entries != null) {
/*  8449 */         for (Provisioning.CacheEntry entry : entries) {
/*  8450 */           Key.ZimletBy zimletBy = entry.mEntryBy == Key.CacheEntryBy.id ? Key.ZimletBy.id : Key.ZimletBy.name;
/*  8451 */           Zimlet zimlet = getFromCache(zimletBy, entry.mEntryIdentity);
/*  8452 */           if (zimlet != null)
/*  8453 */             reload(zimlet, false);
/*       */         }
/*       */       } else
/*  8456 */         this.zimletCache.clear();
/*  8457 */       return;
/*       */     default: 
/*  8459 */       throw ServiceException.INVALID_REQUEST("invalid cache type " + type, null);
/*       */     }
/*       */     
/*       */   }
/*       */   
/*       */   public void removeFromCache(Entry entry)
/*       */   {
/*  8466 */     if ((entry instanceof Account)) {
/*  8467 */       this.accountCache.remove((Account)entry);
/*  8468 */     } else if ((entry instanceof Group)) {
/*  8469 */       this.groupCache.remove((Group)entry);
/*       */     } else
/*  8471 */       throw new UnsupportedOperationException();
/*       */   }
/*       */   
/*       */   private static class CountAccountVisitor implements NamedEntry.Visitor { Provisioning mProv;
/*       */     
/*       */     private static class Result { String mName;
/*       */       long mCount;
/*       */       
/*  8479 */       Result(String name) { this.mName = name;
/*  8480 */         this.mCount = 0L;
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  8487 */     Map<String, Result> mResult = new HashMap();
/*       */     
/*       */     CountAccountVisitor(Provisioning prov) {
/*  8490 */       this.mProv = prov;
/*       */     }
/*       */     
/*       */     public void visit(NamedEntry entry) throws ServiceException
/*       */     {
/*  8495 */       if (!(entry instanceof Account)) {
/*  8496 */         return;
/*       */       }
/*  8498 */       if ((entry instanceof CalendarResource)) {
/*  8499 */         return;
/*       */       }
/*  8501 */       Account acct = (Account)entry;
/*  8502 */       if (acct.getBooleanAttr("zimbraIsSystemResource", false)) {
/*  8503 */         return;
/*       */       }
/*  8505 */       Cos cos = this.mProv.getCOS(acct);
/*  8506 */       Result r = (Result)this.mResult.get(cos.getId());
/*  8507 */       if (r == null) {
/*  8508 */         r = new Result(cos.getName());
/*  8509 */         this.mResult.put(cos.getId(), r);
/*       */       }
/*  8511 */       r.mCount += 1L;
/*       */     }
/*       */     
/*       */     Provisioning.CountAccountResult getResult() {
/*  8515 */       Provisioning.CountAccountResult result = new Provisioning.CountAccountResult();
/*  8516 */       for (Map.Entry<String, Result> r : this.mResult.entrySet()) {
/*  8517 */         result.addCountAccountByCosResult((String)r.getKey(), ((Result)r.getValue()).mName, ((Result)r.getValue()).mCount);
/*       */       }
/*  8519 */       return result;
/*       */     }
/*       */   }
/*       */   
/*       */   public Provisioning.CountAccountResult countAccount(Domain domain) throws ServiceException
/*       */   {
/*  8525 */     CountAccountVisitor visitor = new CountAccountVisitor(this);
/*       */     
/*  8527 */     SearchAccountsOptions option = new SearchAccountsOptions(domain, new String[] { "zimbraCOSId", "zimbraIsSystemResource" });
/*       */     
/*       */ 
/*  8530 */     option.setIncludeType(SearchAccountsOptions.IncludeType.ACCOUNTS_ONLY);
/*  8531 */     option.setFilter(this.mDIT.filterAccountsOnlyByDomain(domain));
/*  8532 */     searchDirectoryInternal(option, visitor);
/*       */     
/*  8534 */     return visitor.getResult();
/*       */   }
/*       */   
/*       */ 
/*       */   public long countObjects(CountObjectsType type, Domain domain, UCService ucService)
/*       */     throws ServiceException
/*       */   {
/*  8541 */     if ((domain != null) && (!type.allowsDomain())) {
/*  8542 */       throw ServiceException.INVALID_REQUEST("domain cannot be specified for counting type: " + type.toString(), null);
/*       */     }
/*       */     
/*       */ 
/*  8546 */     if ((ucService != null) && (!type.allowsUCService())) {
/*  8547 */       throw ServiceException.INVALID_REQUEST("UCService cannot be specified for counting type: " + type.toString(), null);
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  8555 */     Set<SearchDirectoryOptions.ObjectType> types = Sets.newHashSet();
/*       */     ZLdapFilter filter;
/*  8557 */     switch (type) {
/*       */     case userAccount: 
/*  8559 */       types.add(SearchDirectoryOptions.ObjectType.accounts);
/*  8560 */       filter = this.filterFactory.allNonSystemAccounts();
/*  8561 */       break;
/*       */     case internalUserAccount: 
/*  8563 */       types.add(SearchDirectoryOptions.ObjectType.accounts);
/*  8564 */       filter = this.filterFactory.allNonSystemInternalAccounts();
/*  8565 */       break;
/*       */     case internalArchivingAccount: 
/*  8567 */       types.add(SearchDirectoryOptions.ObjectType.accounts);
/*  8568 */       filter = this.filterFactory.allNonSystemArchivingAccounts();
/*  8569 */       break;
/*       */     case account: 
/*  8571 */       types.add(SearchDirectoryOptions.ObjectType.accounts);
/*  8572 */       types.add(SearchDirectoryOptions.ObjectType.resources);
/*  8573 */       filter = this.filterFactory.allAccounts();
/*  8574 */       break;
/*       */     case alias: 
/*  8576 */       types.add(SearchDirectoryOptions.ObjectType.aliases);
/*  8577 */       filter = this.filterFactory.allAliases();
/*  8578 */       break;
/*       */     case dl: 
/*  8580 */       types.add(SearchDirectoryOptions.ObjectType.distributionlists);
/*  8581 */       types.add(SearchDirectoryOptions.ObjectType.dynamicgroups);
/*  8582 */       filter = this.mDIT.filterGroupsByDomain(domain);
/*  8583 */       if ((domain != null) && (!InMemoryLdapServer.isOn())) {
/*  8584 */         ZLdapFilter dnSubtreeMatchFilter = ((LdapDomain)domain).getDnSubtreeMatchFilter();
/*  8585 */         filter = this.filterFactory.andWith(filter, dnSubtreeMatchFilter); }
/*  8586 */       break;
/*       */     
/*       */     case calresource: 
/*  8589 */       types.add(SearchDirectoryOptions.ObjectType.resources);
/*  8590 */       filter = this.filterFactory.allCalendarResources();
/*  8591 */       break;
/*       */     case domain: 
/*  8593 */       types.add(SearchDirectoryOptions.ObjectType.domains);
/*  8594 */       filter = this.filterFactory.allDomains();
/*  8595 */       break;
/*       */     case cos: 
/*  8597 */       types.add(SearchDirectoryOptions.ObjectType.coses);
/*  8598 */       filter = this.filterFactory.allCoses();
/*  8599 */       break;
/*       */     case server: 
/*  8601 */       types.add(SearchDirectoryOptions.ObjectType.servers);
/*  8602 */       filter = this.filterFactory.allServers();
/*  8603 */       break;
/*       */     case accountOnUCService: 
/*  8605 */       if (ucService == null) {
/*  8606 */         throw ServiceException.INVALID_REQUEST("UCService is required for counting type: " + type.toString(), null);
/*       */       }
/*       */       
/*  8609 */       types.add(SearchDirectoryOptions.ObjectType.accounts);
/*  8610 */       types.add(SearchDirectoryOptions.ObjectType.resources);
/*  8611 */       filter = this.filterFactory.accountsOnUCService(ucService.getId());
/*  8612 */       break;
/*       */     case cosOnUCService: 
/*  8614 */       if (ucService == null) {
/*  8615 */         throw ServiceException.INVALID_REQUEST("UCService is required for counting type: " + type.toString(), null);
/*       */       }
/*       */       
/*  8618 */       types.add(SearchDirectoryOptions.ObjectType.coses);
/*  8619 */       filter = this.filterFactory.cosesOnUCService(ucService.getId());
/*  8620 */       break;
/*       */     case domainOnUCService: 
/*  8622 */       if (ucService == null) {
/*  8623 */         throw ServiceException.INVALID_REQUEST("UCService is required for counting type: " + type.toString(), null);
/*       */       }
/*       */       
/*  8626 */       types.add(SearchDirectoryOptions.ObjectType.domains);
/*  8627 */       filter = this.filterFactory.domainsOnUCService(ucService.getId());
/*  8628 */       break;
/*       */     default: 
/*  8630 */       throw ServiceException.INVALID_REQUEST("unsupported counting type:" + type.toString(), null);
/*       */     }
/*       */     
/*  8633 */     String[] bases = getSearchBases(domain, types);
/*       */     
/*  8635 */     long num = 0L;
/*  8636 */     for (String base : bases) {
/*  8637 */       num += countObjects(base, filter);
/*       */     }
/*       */     
/*  8640 */     return num;
/*       */   }
/*       */   
/*       */   private long countObjects(String base, ZLdapFilter filter) throws ServiceException
/*       */   {
/*  8645 */     ZSearchControls searchControls = ZSearchControls.createSearchControls(ZSearchScope.SEARCH_SCOPE_SUBTREE, 0, null);
/*       */     
/*  8647 */     return this.helper.countEntries(base, filter, searchControls);
/*       */   }
/*       */   
/*       */   public Map<String, String> getNamesForIds(Set<String> ids, Provisioning.EntryType type)
/*       */     throws ServiceException
/*       */   {
/*  8653 */     final Map<String, String> result = new HashMap();
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  8658 */     final Provisioning.EntryType entryType = type;
/*       */     Set<String> unresolvedIds;
/*       */     String nameAttr;
/*       */     String base;
/*  8662 */     String objectClass; switch (entryType) {
/*       */     case account: 
/*  8664 */       unresolvedIds = new HashSet();
/*  8665 */       for (String id : ids) {
/*  8666 */         NamedEntry entry = this.accountCache.getById(id);
/*  8667 */         if (entry != null) {
/*  8668 */           result.put(id, entry.getName());
/*       */         } else
/*  8670 */           unresolvedIds.add(id);
/*       */       }
/*  8672 */       nameAttr = "zimbraMailDeliveryAddress";
/*  8673 */       base = this.mDIT.mailBranchBaseDN();
/*  8674 */       objectClass = AttributeClass.OC_zimbraAccount;
/*  8675 */       break;
/*       */     case group: 
/*  8677 */       unresolvedIds = ids;
/*  8678 */       nameAttr = "uid";
/*  8679 */       base = this.mDIT.mailBranchBaseDN();
/*  8680 */       objectClass = AttributeClass.OC_zimbraDistributionList;
/*  8681 */       break;
/*       */     case cos: 
/*  8683 */       unresolvedIds = new HashSet();
/*  8684 */       for (String id : ids) {
/*  8685 */         NamedEntry entry = this.cosCache.getById(id);
/*  8686 */         if (entry != null) {
/*  8687 */           result.put(id, entry.getName());
/*       */         } else
/*  8689 */           unresolvedIds.add(id);
/*       */       }
/*  8691 */       nameAttr = "cn";
/*  8692 */       base = this.mDIT.cosBaseDN();
/*  8693 */       objectClass = AttributeClass.OC_zimbraCOS;
/*  8694 */       break;
/*       */     case domain: 
/*  8696 */       unresolvedIds = new HashSet();
/*  8697 */       for (String id : ids) {
/*  8698 */         NamedEntry entry = getFromCache(Key.DomainBy.id, id, DomainCache.GetFromDomainCacheOption.POSITIVE);
/*  8699 */         if (entry != null) {
/*  8700 */           result.put(id, entry.getName());
/*       */         } else
/*  8702 */           unresolvedIds.add(id);
/*       */       }
/*  8704 */       nameAttr = "zimbraDomainName";
/*  8705 */       base = this.mDIT.domainBaseDN();
/*  8706 */       objectClass = AttributeClass.OC_zimbraDomain;
/*  8707 */       break;
/*       */     default: 
/*  8709 */       throw ServiceException.FAILURE("unsupported entry type for getNamesForIds" + type.name(), null);
/*       */     }
/*       */     
/*       */     
/*  8713 */     if (unresolvedIds.size() == 0) {
/*  8714 */       return result;
/*       */     }
/*  8716 */     SearchLdapOptions.SearchLdapVisitor visitor = new SearchLdapOptions.SearchLdapVisitor()
/*       */     {
/*       */       public void visit(String dn, Map<String, Object> attrs, IAttributes ldapAttrs) {
/*  8719 */         String id = (String)attrs.get("zimbraId");
/*       */         
/*  8721 */         String name = null;
/*       */         try {
/*  8723 */           switch (LdapProvisioning.8.$SwitchMap$com$zimbra$cs$account$Provisioning$EntryType[entryType.ordinal()]) {
/*       */           case 1: 
/*  8725 */             name = ldapAttrs.getAttrString("zimbraMailDeliveryAddress");
/*  8726 */             if (name == null)
/*  8727 */               name = LdapProvisioning.this.mDIT.dnToEmail(dn, ldapAttrs);
/*       */             break;
/*       */           case 2: 
/*  8730 */             name = LdapProvisioning.this.mDIT.dnToEmail(dn, ldapAttrs);
/*  8731 */             break;
/*       */           case 3: 
/*  8733 */             name = ldapAttrs.getAttrString("cn");
/*  8734 */             break;
/*       */           case 4: 
/*  8736 */             name = ldapAttrs.getAttrString("zimbraDomainName");
/*       */           }
/*       */         }
/*       */         catch (ServiceException e) {
/*  8740 */           name = null;
/*       */         }
/*       */         
/*  8743 */         if (name != null) {
/*  8744 */           result.put(id, name);
/*       */         }
/*       */       }
/*  8747 */     };
/*  8748 */     String[] returnAttrs = { "zimbraId", nameAttr };
/*  8749 */     searchNamesForIds(unresolvedIds, base, objectClass, returnAttrs, visitor);
/*       */     
/*  8751 */     return result;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public void searchNamesForIds(Set<String> unresolvedIds, String base, String objectClass, String[] returnAttrs, SearchLdapOptions.SearchLdapVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  8759 */     int batchSize = 10;
/*  8760 */     String queryStart = "(&(objectClass=" + objectClass + ")(|";
/*  8761 */     String queryEnd = "))";
/*       */     
/*  8763 */     StringBuilder query = new StringBuilder();
/*  8764 */     query.append(queryStart);
/*       */     
/*  8766 */     int i = 0;
/*  8767 */     for (String id : unresolvedIds) {
/*  8768 */       query.append("(zimbraId=" + id + ")");
/*  8769 */       i++; if (i % 10 == 0) {
/*  8770 */         query.append("))");
/*  8771 */         searchLdapOnReplica(base, query.toString(), returnAttrs, visitor);
/*  8772 */         query.setLength(0);
/*  8773 */         query.append(queryStart);
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*  8778 */     if (query.length() != queryStart.length()) {
/*  8779 */       query.append("))");
/*  8780 */       searchLdapOnReplica(base, query.toString(), returnAttrs, visitor);
/*       */     }
/*       */   }
/*       */   
/*       */   public Map<String, Map<String, Object>> getDomainSMIMEConfig(Domain domain, String configName)
/*       */     throws ServiceException
/*       */   {
/*  8787 */     LdapSMIMEConfig smime = LdapSMIMEConfig.getInstance(domain);
/*  8788 */     return smime.get(configName);
/*       */   }
/*       */   
/*       */   public void modifyDomainSMIMEConfig(Domain domain, String configName, Map<String, Object> attrs)
/*       */     throws ServiceException
/*       */   {
/*  8794 */     LdapSMIMEConfig smime = LdapSMIMEConfig.getInstance(domain);
/*  8795 */     smime.modify(configName, attrs);
/*       */   }
/*       */   
/*       */   public void removeDomainSMIMEConfig(Domain domain, String configName) throws ServiceException
/*       */   {
/*  8800 */     LdapSMIMEConfig smime = LdapSMIMEConfig.getInstance(domain);
/*  8801 */     smime.remove(configName);
/*       */   }
/*       */   
/*       */   public Map<String, Map<String, Object>> getConfigSMIMEConfig(String configName)
/*       */     throws ServiceException
/*       */   {
/*  8807 */     LdapSMIMEConfig smime = LdapSMIMEConfig.getInstance(getConfig());
/*  8808 */     return smime.get(configName);
/*       */   }
/*       */   
/*       */   public void modifyConfigSMIMEConfig(String configName, Map<String, Object> attrs)
/*       */     throws ServiceException
/*       */   {
/*  8814 */     LdapSMIMEConfig smime = LdapSMIMEConfig.getInstance(getConfig());
/*  8815 */     smime.modify(configName, attrs);
/*       */   }
/*       */   
/*       */   public void removeConfigSMIMEConfig(String configName) throws ServiceException
/*       */   {
/*  8820 */     LdapSMIMEConfig smime = LdapSMIMEConfig.getInstance(getConfig());
/*  8821 */     smime.remove(configName);
/*       */   }
/*       */   
/*       */ 
/*       */   public void searchLdapOnMaster(String base, String filter, String[] returnAttrs, SearchLdapOptions.SearchLdapVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  8828 */     searchZimbraLdap(base, filter, returnAttrs, true, visitor);
/*       */   }
/*       */   
/*       */ 
/*       */   public void searchLdapOnReplica(String base, String filter, String[] returnAttrs, SearchLdapOptions.SearchLdapVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  8835 */     searchZimbraLdap(base, filter, returnAttrs, false, visitor);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   @LdapTODO.TODO
/*       */   public void searchLdapOnMaster(String base, ZLdapFilter filter, String[] returnAttrs, SearchLdapOptions.SearchLdapVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  8844 */     searchLdapOnMaster(base, filter.toFilterString(), returnAttrs, visitor);
/*       */   }
/*       */   
/*       */ 
/*       */   @LdapTODO.TODO
/*       */   public void searchLdapOnReplica(String base, ZLdapFilter filter, String[] returnAttrs, SearchLdapOptions.SearchLdapVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  8852 */     searchLdapOnReplica(base, filter.toFilterString(), returnAttrs, visitor);
/*       */   }
/*       */   
/*       */   private void searchZimbraLdap(String base, String query, String[] returnAttrs, boolean useMaster, SearchLdapOptions.SearchLdapVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  8858 */     SearchLdapOptions searchOptions = new SearchLdapOptions(base, query, returnAttrs, 0, null, ZSearchScope.SEARCH_SCOPE_SUBTREE, visitor);
/*       */     
/*       */ 
/*       */ 
/*  8862 */     ZLdapContext zlc = null;
/*       */     try {
/*  8864 */       zlc = LdapClient.getContext(LdapServerType.get(useMaster), LdapUsage.SEARCH);
/*  8865 */       zlc.searchPaged(searchOptions);
/*       */     } finally {
/*  8867 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   public void waitForLdapServer() {}
/*       */   
/*       */ 
/*       */ 
/*       */   public void alwaysUseMaster() {}
/*       */   
/*       */ 
/*       */   public void dumpLdapSchema(PrintWriter writer)
/*       */     throws ServiceException
/*       */   {
/*  8883 */     ZLdapContext zlc = null;
/*       */     try {
/*  8885 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.GET_SCHEMA);
/*  8886 */       ZLdapSchema schema = zlc.getSchema();
/*       */       
/*  8888 */       for (ZLdapSchema.ZObjectClassDefinition oc : schema.getObjectClasses()) {
/*  8889 */         writer.println(oc.getName());
/*       */       }
/*       */       
/*       */     }
/*       */     catch (ServiceException e)
/*       */     {
/*  8895 */       ZimbraLog.account.warn("unable to get LDAP schema", e);
/*       */     } finally {
/*  8897 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   private boolean addressExists(ZLdapContext zlc, String[] addrs)
/*       */     throws ServiceException
/*       */   {
/*  8906 */     return addressExistsUnderDN(zlc, "", addrs);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */   private boolean addressExistsUnderDN(ZLdapContext zlc, String baseDN, String[] addrs)
/*       */     throws ServiceException
/*       */   {
/*  8914 */     ZLdapFilter filter = this.filterFactory.addrsExist(addrs);
/*  8915 */     ZSearchControls searchControls = ZSearchControls.createSearchControls(ZSearchScope.SEARCH_SCOPE_SUBTREE, 1, null);
/*       */     
/*       */     try
/*       */     {
/*  8919 */       long count = this.helper.countEntries(baseDN, filter, searchControls, zlc, LdapServerType.MASTER);
/*       */       
/*  8921 */       return count > 0L;
/*       */     } catch (LdapException.LdapSizeLimitExceededException e) {}
/*  8923 */     return true;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public Group createGroup(String name, Map<String, Object> attrs, boolean dynamic)
/*       */     throws ServiceException
/*       */   {
/*  8935 */     return dynamic ? createDynamicGroup(name, attrs) : createDistributionList(name, attrs);
/*       */   }
/*       */   
/*       */ 
/*       */   public Group createDelegatedGroup(String name, Map<String, Object> attrs, boolean dynamic, Account creator)
/*       */     throws ServiceException
/*       */   {
/*  8942 */     if (creator == null) {
/*  8943 */       throw ServiceException.INVALID_REQUEST("must have a creator account", null);
/*       */     }
/*       */     
/*  8946 */     Group group = dynamic ? createDynamicGroup(name, attrs, creator) : createDistributionList(name, attrs, creator);
/*       */     
/*       */ 
/*       */ 
/*  8950 */     grantRight(TargetType.dl.getCode(), TargetBy.id, group.getId(), GranteeType.GT_USER.getCode(), GranteeSelector.GranteeBy.id, creator.getId(), null, com.zimbra.cs.account.Group.GroupOwner.GROUP_OWNER_RIGHT.getName(), null);
/*       */     
/*       */ 
/*       */ 
/*  8954 */     return group;
/*       */   }
/*       */   
/*       */   public void deleteGroup(String zimbraId) throws ServiceException
/*       */   {
/*  8959 */     Group group = getGroup(Key.DistributionListBy.id, zimbraId, true);
/*  8960 */     if (group == null) {
/*  8961 */       throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
/*       */     }
/*       */     
/*  8964 */     if (group.isDynamic()) {
/*  8965 */       deleteDynamicGroup((LdapDynamicGroup)group);
/*       */     } else {
/*  8967 */       deleteDistributionList((LdapDistributionList)group);
/*       */     }
/*       */   }
/*       */   
/*       */   public void renameGroup(String zimbraId, String newName) throws ServiceException
/*       */   {
/*  8973 */     Group group = getGroup(Key.DistributionListBy.id, zimbraId, true);
/*  8974 */     if (group == null) {
/*  8975 */       throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
/*       */     }
/*       */     
/*  8978 */     if (group.isDynamic()) {
/*  8979 */       renameDynamicGroup(zimbraId, newName);
/*       */     } else {
/*  8981 */       renameDistributionList(zimbraId, newName);
/*       */     }
/*       */   }
/*       */   
/*       */   public Group getGroup(Key.DistributionListBy keyType, String key) throws ServiceException
/*       */   {
/*  8987 */     return getGroup(keyType, key, false);
/*       */   }
/*       */   
/*       */   public Group getGroup(Key.DistributionListBy keyType, String key, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*  8993 */     return getGroupInternal(keyType, key, false, loadFromMaster);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public Group getGroupBasic(Key.DistributionListBy keyType, String key)
/*       */     throws ServiceException
/*       */   {
/*  9006 */     Group group = getGroupFromCache(keyType, key);
/*  9007 */     if (group != null) {
/*  9008 */       return group;
/*       */     }
/*       */     
/*       */ 
/*  9012 */     group = getGroupInternal(keyType, key, true, false);
/*       */     
/*       */ 
/*  9015 */     if (group != null) {
/*  9016 */       putInGroupCache(group);
/*       */     }
/*       */     
/*  9019 */     return group;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   public List getAllGroups(Domain domain)
/*       */     throws ServiceException
/*       */   {
/*  9028 */     SearchDirectoryOptions searchOpts = new SearchDirectoryOptions(domain);
/*  9029 */     searchOpts.setFilter(this.mDIT.filterGroupsByDomain(domain));
/*       */     
/*  9031 */     searchOpts.setTypes(new SearchDirectoryOptions.ObjectType[] { SearchDirectoryOptions.ObjectType.distributionlists, SearchDirectoryOptions.ObjectType.dynamicgroups });
/*  9032 */     searchOpts.setSortOpt(SearchDirectoryOptions.SortOpt.SORT_ASCENDING);
/*  9033 */     List<NamedEntry> groups = searchDirectoryInternal(searchOpts);
/*       */     
/*  9035 */     return groups;
/*       */   }
/*       */   
/*       */   public void addGroupMembers(Group group, String[] members) throws ServiceException
/*       */   {
/*  9040 */     if (group.isDynamic()) {
/*  9041 */       addDynamicGroupMembers((LdapDynamicGroup)group, members);
/*       */     } else {
/*  9043 */       addDistributionListMembers((LdapDistributionList)group, members);
/*       */     }
/*       */   }
/*       */   
/*       */   public void removeGroupMembers(Group group, String[] members) throws ServiceException
/*       */   {
/*  9049 */     if (group.isDynamic()) {
/*  9050 */       removeDynamicGroupMembers((LdapDynamicGroup)group, members, false);
/*       */     } else {
/*  9052 */       removeDistributionListMembers((LdapDistributionList)group, members);
/*       */     }
/*       */   }
/*       */   
/*       */   public void addGroupAlias(Group group, String alias) throws ServiceException
/*       */   {
/*  9058 */     addAliasInternal(group, alias);
/*  9059 */     this.allDLs.addGroup(group);
/*       */   }
/*       */   
/*       */   public void removeGroupAlias(Group group, String alias) throws ServiceException
/*       */   {
/*  9064 */     this.groupCache.remove(group);
/*  9065 */     removeAliasInternal(group, alias);
/*  9066 */     this.allDLs.removeGroup(alias);
/*       */   }
/*       */   
/*       */   public Set<String> getGroups(Account acct) throws ServiceException
/*       */   {
/*  9071 */     Provisioning.GroupMembership groupMembership = getGroupMembership(acct, false);
/*  9072 */     return Sets.newHashSet(groupMembership.groupIds());
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public List<Group> getGroups(Account acct, boolean directOnly, Map<String, String> via)
/*       */     throws ServiceException
/*       */   {
/*  9086 */     List<DistributionList> dls = getDistributionLists(acct, directOnly, via);
/*       */     
/*       */ 
/*  9089 */     List<DynamicGroup> dynGroups = getContainingDynamicGroups(acct);
/*       */     
/*  9091 */     List<Group> groups = Lists.newArrayList();
/*  9092 */     groups.addAll(dls);
/*  9093 */     groups.addAll(dynGroups);
/*       */     
/*  9095 */     return groups;
/*       */   }
/*       */   
/*       */   public boolean inACLGroup(Account acct, String zimbraId)
/*       */     throws ServiceException
/*       */   {
/*  9101 */     Provisioning.GroupMembership membership = getGroupMembership(acct, false);
/*  9102 */     return membership.groupIds().contains(zimbraId);
/*       */   }
/*       */   
/*       */   public String[] getGroupMembers(Group group) throws ServiceException
/*       */   {
/*  9107 */     EntryCacheDataKey cacheKey = EntryCacheDataKey.GROUP_MEMBERS;
/*       */     
/*  9109 */     String[] members = (String[])group.getCachedData(cacheKey);
/*  9110 */     if (members != null) {
/*  9111 */       return members;
/*       */     }
/*       */     
/*  9114 */     members = group.getAllMembers();
/*  9115 */     assert (members != null);
/*  9116 */     Arrays.sort(members);
/*       */     
/*       */ 
/*  9119 */     group.setCachedData(cacheKey, members);
/*       */     
/*  9121 */     return members;
/*       */   }
/*       */   
/*       */   public Provisioning.GroupMemberEmailAddrs getMemberAddrs(Group group)
/*       */     throws ServiceException
/*       */   {
/*  9127 */     group = getGroup(Key.DistributionListBy.id, group.getId());
/*       */     
/*  9129 */     Provisioning.GroupMemberEmailAddrs addrs = new Provisioning.GroupMemberEmailAddrs();
/*  9130 */     if (group.isDynamic()) {
/*  9131 */       LdapDynamicGroup ldapDynGroup = (LdapDynamicGroup)group;
/*  9132 */       if (ldapDynGroup.isMembershipDefinedByCustomURL()) {
/*  9133 */         addrs.setGroupAddr(group.getName());
/*       */       }
/*  9135 */       else if (ldapDynGroup.hasExternalMembers())
/*       */       {
/*  9137 */         List<String> internalMembers = Lists.newArrayList();
/*  9138 */         searchDynamicGroupInternalMemberDeliveryAddresses(null, group.getId(), internalMembers);
/*  9139 */         if (!internalMembers.isEmpty()) {
/*  9140 */           addrs.setInternalAddrs(internalMembers);
/*       */         }
/*       */         
/*       */ 
/*  9144 */         addrs.setExternalAddrs(ldapDynGroup.getStaticUnit().getMembersSet());
/*       */       } else {
/*  9146 */         addrs.setGroupAddr(group.getName());
/*       */       }
/*       */     }
/*       */     else {
/*  9150 */       String[] members = getGroupMembers(group);
/*  9151 */       Set<String> internalMembers = Sets.newHashSet();
/*  9152 */       Set<String> externalMembers = Sets.newHashSet();
/*  9153 */       ZLdapContext zlc = LdapClient.getContext(LdapServerType.REPLICA, LdapUsage.SEARCH);
/*       */       try {
/*  9155 */         for (String member : members) {
/*  9156 */           if (addressExists(zlc, new String[] { member })) {
/*  9157 */             internalMembers.add(member);
/*       */           } else {
/*  9159 */             externalMembers.add(member);
/*       */           }
/*       */         }
/*       */       } finally {
/*  9163 */         LdapClient.closeContext(zlc);
/*       */       }
/*  9165 */       if (!externalMembers.isEmpty()) {
/*  9166 */         if (!internalMembers.isEmpty()) {
/*  9167 */           addrs.setInternalAddrs(internalMembers);
/*       */         }
/*  9169 */         addrs.setExternalAddrs(externalMembers);
/*       */       } else {
/*  9171 */         addrs.setGroupAddr(group.getName());
/*       */       }
/*       */     }
/*  9174 */     return addrs;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void cleanGroupMembersCache(Group group)
/*       */   {
/*  9186 */     Group cachedInstance = getGroupFromCache(Key.DistributionListBy.id, group.getId());
/*  9187 */     if ((cachedInstance != null) && (group != cachedInstance)) {
/*  9188 */       cachedInstance.removeCachedData(EntryCacheDataKey.GROUP_MEMBERS);
/*       */     }
/*       */     
/*       */ 
/*  9192 */     group.removeCachedData(EntryCacheDataKey.GROUP_MEMBERS);
/*       */   }
/*       */   
/*       */   private Group getGroupInternal(Key.DistributionListBy keyType, String key, boolean basicAttrsOnly, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*  9198 */     switch (keyType) {
/*       */     case id: 
/*  9200 */       return getGroupById(key, null, basicAttrsOnly, loadFromMaster);
/*       */     case name: 
/*  9202 */       Group group = getGroupByName(key, null, basicAttrsOnly, loadFromMaster);
/*  9203 */       if (group == null) {
/*  9204 */         String localDomainAddr = getEmailAddrByDomainAlias(key);
/*  9205 */         if (localDomainAddr != null) {
/*  9206 */           group = getGroupByName(localDomainAddr, null, basicAttrsOnly, loadFromMaster);
/*       */         }
/*       */       }
/*  9209 */       return group;
/*       */     }
/*  9211 */     return null;
/*       */   }
/*       */   
/*       */ 
/*       */   private Group getGroupById(String zimbraId, ZLdapContext zlc, boolean basicAttrsOnly, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*  9218 */     return getGroupByQuery(this.filterFactory.groupById(zimbraId), zlc, basicAttrsOnly, loadFromMaster);
/*       */   }
/*       */   
/*       */   private Group getGroupByName(String groupAddress, ZLdapContext zlc, boolean basicAttrsOnly, boolean loadFromMaster)
/*       */     throws ServiceException
/*       */   {
/*  9224 */     groupAddress = IDNUtil.toAsciiEmail(groupAddress);
/*  9225 */     return getGroupByQuery(this.filterFactory.groupByName(groupAddress), zlc, basicAttrsOnly, loadFromMaster);
/*       */   }
/*       */   
/*       */   private Group getGroupByQuery(ZLdapFilter filter, ZLdapContext initZlc, boolean basicAttrsOnly, boolean loadFromMaster) throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/*  9232 */       String[] returnAttrs = basicAttrsOnly ? this.BASIC_GROUP_ATTRS : null;
/*  9233 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.mailBranchBaseDN(), filter, initZlc, loadFromMaster, returnAttrs);
/*       */       
/*  9235 */       if (sr != null) {
/*  9236 */         ZAttributes attrs = sr.getAttributes();
/*  9237 */         List<String> objectclass = attrs.getMultiAttrStringAsList("objectClass", IAttributes.CheckBinary.NOCHECK);
/*       */         
/*       */ 
/*  9240 */         if (objectclass.contains(AttributeClass.OC_zimbraDistributionList))
/*  9241 */           return makeDistributionList(sr.getDN(), attrs, basicAttrsOnly);
/*  9242 */         if (objectclass.contains(AttributeClass.OC_zimbraGroup)) {
/*  9243 */           return makeDynamicGroup(initZlc, sr.getDN(), attrs);
/*       */         }
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  9247 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getGroupByQuery", e);
/*       */     } catch (ServiceException e) {
/*  9249 */       throw ServiceException.FAILURE("unable to lookup group via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  9252 */     return null;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void setGroupHomeServer(ZMutableEntry entry, Account creator)
/*       */     throws ServiceException
/*       */   {
/*  9265 */     Cos cosOfCreator = null;
/*  9266 */     if (creator != null) {
/*  9267 */       cosOfCreator = getCOS(creator);
/*       */     }
/*  9269 */     addMailHost(entry, cosOfCreator, false);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   public DynamicGroup createDynamicGroup(String groupAddress, Map<String, Object> groupAttrs)
/*       */     throws ServiceException
/*       */   {
/*  9283 */     return createDynamicGroup(groupAddress, groupAttrs, null);
/*       */   }
/*       */   
/*       */   private String dynamicGroupDynamicUnitLocalpart(String dynamicGroupLocalpart) {
/*  9287 */     return dynamicGroupLocalpart + ".__internal__";
/*       */   }
/*       */   
/*       */   private String dynamicGroupStaticUnitLocalpart(String dynamicGroupLocalpart) {
/*  9291 */     return dynamicGroupLocalpart + ".__external__";
/*       */   }
/*       */   
/*       */ 
/*       */   private DynamicGroup createDynamicGroup(String groupAddress, Map<String, Object> groupAttrs, Account creator)
/*       */     throws ServiceException
/*       */   {
/*  9298 */     SpecialAttrs specialAttrs = this.mDIT.handleSpecialAttrs(groupAttrs);
/*  9299 */     String baseDn = specialAttrs.getLdapBaseDn();
/*       */     
/*  9301 */     groupAddress = groupAddress.toLowerCase().trim();
/*  9302 */     NameUtil.EmailAddress addr = new NameUtil.EmailAddress(groupAddress);
/*       */     
/*  9304 */     String localPart = addr.getLocalPart();
/*  9305 */     String domainName = addr.getDomain();
/*  9306 */     domainName = IDNUtil.toAsciiDomainName(domainName);
/*  9307 */     groupAddress = NameUtil.EmailAddress.getAddress(localPart, domainName);
/*       */     
/*  9309 */     validEmailAddress(groupAddress);
/*       */     
/*  9311 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/*  9312 */     callbackContext.setCreatingEntryName(groupAddress);
/*       */     
/*       */ 
/*  9315 */     Object providedZimbraIsACLGroup = groupAttrs.get("zimbraIsACLGroup");
/*  9316 */     if (providedZimbraIsACLGroup != null) {
/*  9317 */       groupAttrs.remove("zimbraIsACLGroup");
/*       */     }
/*       */     
/*  9320 */     AttributeManager.getInstance().preModify(groupAttrs, null, callbackContext, true);
/*       */     
/*       */ 
/*  9323 */     if (providedZimbraIsACLGroup != null) {
/*  9324 */       groupAttrs.put("zimbraIsACLGroup", providedZimbraIsACLGroup);
/*       */     }
/*       */     
/*  9327 */     ZLdapContext zlc = null;
/*       */     try {
/*  9329 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_DYNAMICGROUP);
/*       */       
/*  9331 */       Domain domain = getDomainByAsciiName(domainName, zlc);
/*  9332 */       if (domain == null) {
/*  9333 */         throw AccountServiceException.NO_SUCH_DOMAIN(domainName);
/*       */       }
/*       */       
/*  9336 */       if (!domain.isLocal()) {
/*  9337 */         throw ServiceException.INVALID_REQUEST("domain type must be local", null);
/*       */       }
/*       */       
/*  9340 */       String domainDN = ((LdapDomain)domain).getDN();
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9347 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/*  9348 */       entry.mapToAttrs(groupAttrs);
/*       */       
/*  9350 */       Set<String> ocs = LdapObjectClass.getGroupObjectClasses(this);
/*  9351 */       entry.addAttr("objectClass", ocs);
/*       */       
/*  9353 */       String zimbraId = LdapUtil.generateUUID();
/*       */       
/*       */ 
/*  9356 */       String staticUnitZimbraId = LdapUtil.generateUUID();
/*       */       
/*  9358 */       String createTimestamp = DateUtil.toGeneralizedTime(new Date());
/*  9359 */       entry.setAttr("zimbraId", zimbraId);
/*  9360 */       entry.setAttr("zimbraCreateTimestamp", createTimestamp);
/*  9361 */       entry.setAttr("mail", groupAddress);
/*  9362 */       entry.setAttr("dgIdentity", LC.zimbra_ldap_userdn.value());
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9368 */       entry.setAttr("zimbraMailAlias", groupAddress);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9376 */       String specifiedIsACLGroup = entry.getAttrString("zimbraIsACLGroup");
/*       */       boolean isACLGroup;
/*  9378 */       boolean isACLGroup; if (!entry.hasAttribute("memberURL")) {
/*  9379 */         String memberURL = LdapDynamicGroup.getDefaultMemberURL(zimbraId, staticUnitZimbraId);
/*  9380 */         entry.setAttr("memberURL", memberURL);
/*       */         
/*       */ 
/*       */ 
/*  9384 */         if (specifiedIsACLGroup == null) {
/*  9385 */           entry.setAttr("zimbraIsACLGroup", "TRUE");
/*  9386 */         } else if ("FALSE".equals(specifiedIsACLGroup)) {
/*  9387 */           throw ServiceException.INVALID_REQUEST("No custom memberURL is provided, zimbraIsACLGroup cannot be set to FALSE", null);
/*       */         }
/*       */         
/*       */ 
/*  9391 */         isACLGroup = true;
/*       */ 
/*       */       }
/*       */       else
/*       */       {
/*  9396 */         isACLGroup = !"FALSE".equals(specifiedIsACLGroup);
/*       */       }
/*       */       
/*       */ 
/*  9400 */       if (!entry.hasAttribute("zimbraMailStatus")) {
/*  9401 */         entry.setAttr("zimbraMailStatus", "enabled");
/*       */       }
/*  9403 */       String mailStatus = entry.getAttrString("zimbraMailStatus");
/*       */       
/*  9405 */       entry.setAttr("cn", localPart);
/*       */       
/*       */ 
/*  9408 */       setGroupHomeServer(entry, creator);
/*       */       
/*  9410 */       String dn = this.mDIT.dynamicGroupNameLocalPartToDN(localPart, domainDN);
/*  9411 */       entry.setDN(dn);
/*       */       
/*  9413 */       zlc.createEntry(entry);
/*       */       String dynamicUnitAddr;
/*  9415 */       if (isACLGroup)
/*       */       {
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9421 */         String dynamicUnitLocalpart = dynamicGroupDynamicUnitLocalpart(localPart);
/*  9422 */         dynamicUnitAddr = NameUtil.EmailAddress.getAddress(dynamicUnitLocalpart, domainName);
/*  9423 */         entry = LdapClient.createMutableEntry();
/*  9424 */         ocs = LdapObjectClass.getGroupDynamicUnitObjectClasses(this);
/*  9425 */         entry.addAttr("objectClass", ocs);
/*       */         
/*  9427 */         String dynamicUnitZimbraId = LdapUtil.generateUUID();
/*  9428 */         entry.setAttr("cn", "internal");
/*  9429 */         entry.setAttr("zimbraId", dynamicUnitZimbraId);
/*  9430 */         entry.setAttr("zimbraGroupId", zimbraId);
/*  9431 */         entry.setAttr("zimbraCreateTimestamp", createTimestamp);
/*  9432 */         entry.setAttr("mail", dynamicUnitAddr);
/*  9433 */         entry.setAttr("zimbraMailAlias", dynamicUnitAddr);
/*  9434 */         entry.setAttr("zimbraMailStatus", mailStatus);
/*       */         
/*  9436 */         entry.setAttr("dgIdentity", LC.zimbra_ldap_userdn.value());
/*  9437 */         String memberURL = LdapDynamicGroup.getDefaultDynamicUnitMemberURL(zimbraId);
/*  9438 */         entry.setAttr("memberURL", memberURL);
/*       */         
/*  9440 */         String dynamicUnitDN = this.mDIT.dynamicGroupUnitNameToDN("internal", dn);
/*       */         
/*  9442 */         entry.setDN(dynamicUnitDN);
/*       */         
/*  9444 */         zlc.createEntry(entry);
/*       */         
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9451 */         entry = LdapClient.createMutableEntry();
/*  9452 */         ocs = LdapObjectClass.getGroupStaticUnitObjectClasses(this);
/*  9453 */         entry.addAttr("objectClass", ocs);
/*       */         
/*  9455 */         entry.setAttr("cn", "external");
/*  9456 */         entry.setAttr("zimbraId", staticUnitZimbraId);
/*  9457 */         entry.setAttr("zimbraGroupId", zimbraId);
/*  9458 */         entry.setAttr("zimbraCreateTimestamp", createTimestamp);
/*       */         
/*  9460 */         String staticUnitDN = this.mDIT.dynamicGroupUnitNameToDN("external", dn);
/*       */         
/*  9462 */         entry.setDN(staticUnitDN);
/*       */         
/*  9464 */         zlc.createEntry(entry);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  9470 */       DynamicGroup group = getDynamicGroupBasic(Key.DistributionListBy.id, zimbraId, zlc);
/*       */       
/*  9472 */       if (group != null) {
/*  9473 */         AttributeManager.getInstance().postModify(groupAttrs, group, callbackContext);
/*  9474 */         removeExternalAddrsFromAllDynamicGroups(group.getAllAddrsSet(), zlc);
/*  9475 */         this.allDLs.addGroup(group);
/*       */       } else {
/*  9477 */         throw ServiceException.FAILURE("unable to get dynamic group after creating LDAP entry: " + groupAddress, null);
/*       */       }
/*       */       
/*  9480 */       return group;
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  9483 */       throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(groupAddress);
/*       */     } catch (LdapException e) {
/*  9485 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  9487 */       throw e;
/*       */     } finally {
/*  9489 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   private void deleteDynamicGroup(LdapDynamicGroup group) throws ServiceException {
/*  9494 */     String zimbraId = group.getId();
/*       */     
/*       */ 
/*       */ 
/*  9498 */     Set<String> addrs = new HashSet(group.getMultiAttrSet("mail"));
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9506 */     String[] aliases = group.getAliases();
/*  9507 */     if (aliases != null) {
/*  9508 */       String groupName = group.getName();
/*  9509 */       for (int i = 0; i < aliases.length; i++)
/*       */       {
/*       */ 
/*  9512 */         if (!groupName.equalsIgnoreCase(aliases[i])) {
/*  9513 */           removeGroupAlias(group, aliases[i]);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9529 */     ZLdapContext zlc = null;
/*       */     try {
/*  9531 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_DYNAMICGROUP);
/*       */       
/*  9533 */       String dn = group.getDN();
/*  9534 */       zlc.deleteChildren(dn);
/*  9535 */       zlc.deleteEntry(dn);
/*       */       
/*       */ 
/*  9538 */       deleteMemberOfOnAccounts(zlc, zimbraId);
/*  9539 */       this.groupCache.remove(group);
/*  9540 */       this.allDLs.removeGroup(addrs);
/*       */     } catch (ServiceException e) {
/*  9542 */       throw ServiceException.FAILURE("unable to purge group: " + zimbraId, e);
/*       */     } finally {
/*  9544 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/*  9547 */     PermissionCache.invalidateCache();
/*       */   }
/*       */   
/*       */   private void searchDynamicGroupInternalMembers(ZLdapContext zlc, String dynGroupId, SearchLdapOptions.SearchLdapVisitor visitor)
/*       */     throws ServiceException
/*       */   {
/*  9553 */     String base = this.mDIT.mailBranchBaseDN();
/*  9554 */     ZLdapFilter filter = this.filterFactory.accountByMemberOf(dynGroupId);
/*       */     
/*  9556 */     SearchLdapOptions searchOptions = new SearchLdapOptions(base, filter, new String[] { "zimbraMailDeliveryAddress", "zimbraMemberOf" }, 0, null, ZSearchScope.SEARCH_SCOPE_SUBTREE, visitor);
/*       */     
/*       */ 
/*       */ 
/*       */ 
/*  9561 */     zlc.searchPaged(searchOptions);
/*       */   }
/*       */   
/*       */   private void deleteMemberOfOnAccounts(ZLdapContext zlc, String dynGroupId)
/*       */     throws ServiceException
/*       */   {
/*  9567 */     final List<Account> accts = new ArrayList();
/*  9568 */     SearchLdapOptions.SearchLdapVisitor visitor = new SearchLdapOptions.SearchLdapVisitor(false)
/*       */     {
/*       */       public void visit(String dn, IAttributes ldapAttrs) throws SearchLdapOptions.StopIteratingException
/*       */       {
/*       */         try {
/*  9573 */           Account acct = LdapProvisioning.this.makeAccountNoDefaults(dn, (ZAttributes)ldapAttrs);
/*  9574 */           accts.add(acct);
/*       */         } catch (ServiceException e) {
/*  9576 */           ZimbraLog.account.warn("unable to make account " + dn, e);
/*       */         }
/*       */       }
/*  9579 */     };
/*  9580 */     searchDynamicGroupInternalMembers(zlc, dynGroupId, visitor);
/*       */     
/*       */ 
/*       */ 
/*  9584 */     for (Account acct : accts) {
/*  9585 */       Map<String, Object> attrs = new HashMap();
/*  9586 */       attrs.put("-zimbraMemberOf", dynGroupId);
/*  9587 */       modifyLdapAttrs(acct, zlc, attrs);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9593 */       Account cached = getFromCache(Key.AccountBy.name, acct.getName());
/*  9594 */       if (cached != null) {
/*  9595 */         removeFromCache(cached);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   private void renameDynamicGroup(String zimbraId, String newEmail) throws ServiceException {
/*  9601 */     newEmail = IDNUtil.toAsciiEmail(newEmail);
/*  9602 */     validEmailAddress(newEmail);
/*       */     
/*  9604 */     boolean domainChanged = false;
/*  9605 */     ZLdapContext zlc = null;
/*       */     try {
/*  9607 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_DYNAMICGROUP);
/*       */       
/*  9609 */       LdapDynamicGroup group = (LdapDynamicGroup)getDynamicGroupById(zimbraId, zlc, false);
/*  9610 */       if (group == null) {
/*  9611 */         throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
/*       */       }
/*       */       
/*       */ 
/*  9615 */       this.groupCache.remove(group);
/*       */       
/*  9617 */       String oldEmail = group.getName();
/*  9618 */       String oldDomain = EmailUtil.getValidDomainPart(oldEmail);
/*       */       
/*  9620 */       newEmail = newEmail.toLowerCase().trim();
/*  9621 */       String[] parts = EmailUtil.getLocalPartAndDomain(newEmail);
/*  9622 */       if (parts == null) {
/*  9623 */         throw ServiceException.INVALID_REQUEST("bad value for newName", null);
/*       */       }
/*  9625 */       String newLocal = parts[0];
/*  9626 */       String newDomain = parts[1];
/*       */       
/*  9628 */       domainChanged = !oldDomain.equals(newDomain);
/*       */       
/*  9630 */       Domain domain = getDomainByAsciiName(newDomain, zlc);
/*  9631 */       if (domain == null) {
/*  9632 */         throw AccountServiceException.NO_SUCH_DOMAIN(newDomain);
/*       */       }
/*       */       
/*  9635 */       if (domainChanged)
/*       */       {
/*  9637 */         if (!domain.isLocal()) {
/*  9638 */           throw ServiceException.INVALID_REQUEST("domain type must be local", null);
/*       */         }
/*       */       }
/*       */       
/*  9642 */       Map<String, Object> attrs = new HashMap();
/*       */       
/*  9644 */       ReplaceAddressResult replacedMails = replaceMailAddresses(group, "mail", oldEmail, newEmail);
/*  9645 */       if (replacedMails.newAddrs().length == 0)
/*       */       {
/*  9647 */         attrs.put("mail", newEmail);
/*       */       } else {
/*  9649 */         attrs.put("mail", replacedMails.newAddrs());
/*       */       }
/*       */       
/*  9652 */       ReplaceAddressResult replacedAliases = replaceMailAddresses(group, "zimbraMailAlias", oldEmail, newEmail);
/*  9653 */       if (replacedAliases.newAddrs().length > 0) {
/*  9654 */         attrs.put("zimbraMailAlias", replacedAliases.newAddrs());
/*       */         
/*  9656 */         String newDomainDN = this.mDIT.domainToAccountSearchDN(newDomain);
/*       */         
/*       */ 
/*  9659 */         if ((domainChanged) && (addressExistsUnderDN(zlc, newDomainDN, replacedAliases.newAddrs()))) {
/*  9660 */           throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
/*       */         }
/*       */       }
/*       */       
/*  9664 */       ReplaceAddressResult replacedAllowAddrForDelegatedSender = replaceMailAddresses(group, "zimbraPrefAllowAddressForDelegatedSender", oldEmail, newEmail);
/*       */       
/*       */ 
/*  9667 */       if (replacedAllowAddrForDelegatedSender.newAddrs().length > 0) {
/*  9668 */         attrs.put("zimbraPrefAllowAddressForDelegatedSender", replacedAllowAddrForDelegatedSender.newAddrs());
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*  9673 */       String rdnAttrName = this.mDIT.dynamicGroupNamingRdnAttr();
/*  9674 */       attrs.put(rdnAttrName, newLocal);
/*       */       
/*       */ 
/*  9677 */       String oldDn = group.getDN();
/*  9678 */       String newDn = this.mDIT.dynamicGroupDNRename(oldDn, newLocal, domain.getName());
/*  9679 */       boolean dnChanged = !oldDn.equals(newDn);
/*       */       
/*  9681 */       if (dnChanged)
/*       */       {
/*       */ 
/*       */ 
/*  9685 */         attrs.remove("cn");
/*       */         
/*  9687 */         zlc.renameEntry(oldDn, newDn);
/*       */       }
/*       */       
/*       */ 
/*  9691 */       group = (LdapDynamicGroup)getDynamicGroupById(zimbraId, zlc, false);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9701 */       if (domainChanged) {
/*  9702 */         String newUid = group.getAttr(rdnAttrName);
/*  9703 */         moveAliases(zlc, replacedAliases, newDomain, newUid, oldDn, newDn, oldDomain, newDomain);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */       try
/*       */       {
/*  9710 */         modifyAttrsInternal(group, zlc, attrs);
/*       */         
/*       */ 
/*  9713 */         String dynamicUnitNewLocal = dynamicGroupDynamicUnitLocalpart(newLocal);
/*  9714 */         String dynamicUnitNewEmail = dynamicUnitNewLocal + "@" + newDomain;
/*  9715 */         String dynamicUnitDN = this.mDIT.dynamicGroupUnitNameToDN("internal", newDn);
/*       */         
/*       */ 
/*  9718 */         ZMutableEntry entry = LdapClient.createMutableEntry();
/*  9719 */         entry.setAttr("mail", dynamicUnitNewEmail);
/*  9720 */         entry.setAttr("zimbraMailAlias", dynamicUnitNewEmail);
/*  9721 */         zlc.replaceAttributes(dynamicUnitDN, entry.getAttributes());
/*       */       }
/*       */       catch (ServiceException e) {
/*  9724 */         ZimbraLog.account.error("dynamic group renamed to " + newLocal + " but failed to move old name's LDAP attributes", e);
/*       */         
/*  9726 */         throw e;
/*       */       }
/*       */       
/*  9729 */       removeExternalAddrsFromAllDynamicGroups(group.getAllAddrsSet(), zlc);
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/*  9732 */       throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
/*       */     } catch (LdapException e) {
/*  9734 */       throw e;
/*       */     } catch (AccountServiceException e) {
/*  9736 */       throw e;
/*       */     } catch (ServiceException e) {
/*  9738 */       throw ServiceException.FAILURE("unable to rename dynamic group: " + zimbraId, e);
/*       */     } finally {
/*  9740 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/*  9743 */     if (domainChanged) {
/*  9744 */       PermissionCache.invalidateCache();
/*       */     }
/*       */   }
/*       */   
/*       */   private DynamicGroup getDynamicGroupFromCache(Key.DistributionListBy keyType, String key) {
/*  9749 */     Group group = getGroupFromCache(keyType, key);
/*  9750 */     if ((group instanceof DynamicGroup)) {
/*  9751 */       return (DynamicGroup)group;
/*       */     }
/*  9753 */     return null;
/*       */   }
/*       */   
/*       */   private DynamicGroup getDynamicGroupBasic(Key.DistributionListBy keyType, String key, ZLdapContext zlc)
/*       */     throws ServiceException
/*       */   {
/*  9759 */     DynamicGroup dynGroup = getDynamicGroupFromCache(keyType, key);
/*  9760 */     if (dynGroup != null) {
/*  9761 */       return dynGroup;
/*       */     }
/*       */     
/*  9764 */     switch (keyType) {
/*       */     case id: 
/*  9766 */       dynGroup = getDynamicGroupById(key, zlc, true);
/*  9767 */       break;
/*       */     case name: 
/*  9769 */       dynGroup = getDynamicGroupByName(key, zlc, true);
/*       */     }
/*       */     
/*       */     
/*  9773 */     if (dynGroup != null) {
/*  9774 */       putInGroupCache(dynGroup);
/*       */     }
/*  9776 */     return dynGroup;
/*       */   }
/*       */   
/*       */   private DynamicGroup getDynamicGroupById(String zimbraId, ZLdapContext zlc, boolean basicAttrsOnly) throws ServiceException
/*       */   {
/*  9781 */     return getDynamicGroupByQuery(this.filterFactory.dynamicGroupById(zimbraId), zlc, basicAttrsOnly);
/*       */   }
/*       */   
/*       */   private DynamicGroup getDynamicGroupByName(String groupAddress, ZLdapContext zlc, boolean basicAttrsOnly)
/*       */     throws ServiceException
/*       */   {
/*  9787 */     groupAddress = IDNUtil.toAsciiEmail(groupAddress);
/*  9788 */     return getDynamicGroupByQuery(this.filterFactory.dynamicGroupByName(groupAddress), zlc, basicAttrsOnly);
/*       */   }
/*       */   
/*       */   private DynamicGroup getDynamicGroupByQuery(ZLdapFilter filter, ZLdapContext initZlc, boolean basicAttrsOnly) throws ServiceException
/*       */   {
/*       */     try {
/*  9794 */       String[] returnAttrs = basicAttrsOnly ? this.BASIC_DYNAMIC_GROUP_ATTRS : null;
/*  9795 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.mailBranchBaseDN(), filter, initZlc, false, returnAttrs);
/*  9796 */       if (sr != null) {
/*  9797 */         return makeDynamicGroup(initZlc, sr.getDN(), sr.getAttributes());
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/*  9800 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getDynamicGroupByQuery", e);
/*       */     } catch (ServiceException e) {
/*  9802 */       throw ServiceException.FAILURE("unable to lookup group via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/*  9805 */     return null;
/*       */   }
/*       */   
/*       */   private void addDynamicGroupMembers(LdapDynamicGroup group, String[] members) throws ServiceException
/*       */   {
/*  9810 */     if (group.isMembershipDefinedByCustomURL()) {
/*  9811 */       throw ServiceException.INVALID_REQUEST("cannot add members to dynamic group with custom memberURL", null);
/*       */     }
/*       */     
/*       */ 
/*  9815 */     String groupId = group.getId();
/*       */     
/*  9817 */     List<Account> accts = new ArrayList();
/*  9818 */     List<String> externalAddrs = new ArrayList();
/*       */     
/*       */ 
/*  9821 */     for (String member : members) {
/*  9822 */       String memberName = member.toLowerCase();
/*  9823 */       memberName = IDNUtil.toAsciiEmail(memberName);
/*       */       
/*  9825 */       Account acct = get(Key.AccountBy.name, memberName);
/*  9826 */       if (acct == null)
/*       */       {
/*       */ 
/*  9829 */         externalAddrs.add(memberName);
/*       */       }
/*       */       else {
/*  9832 */         Set<String> memberOf = acct.getMultiAttrSet("zimbraMemberOf");
/*  9833 */         if (!memberOf.contains(groupId)) {
/*  9834 */           accts.add(acct);
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*       */ 
/*  9840 */     ZLdapContext zlc = null;
/*       */     try {
/*  9842 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.ADD_GROUP_MEMBER);
/*       */       
/*       */ 
/*       */ 
/*  9846 */       if ((!externalAddrs.isEmpty()) && 
/*  9847 */         (addressExists(zlc, (String[])externalAddrs.toArray(new String[externalAddrs.size()])))) {
/*  9848 */         throw ServiceException.INVALID_REQUEST("address cannot be a group: " + Arrays.deepToString(externalAddrs.toArray()), null);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*  9856 */       for (Account acct : accts) {
/*  9857 */         Map<String, Object> attrs = new HashMap();
/*  9858 */         attrs.put("+zimbraMemberOf", groupId);
/*  9859 */         modifyLdapAttrs(acct, zlc, attrs);
/*  9860 */         clearUpwardMembershipCache(acct);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  9866 */       LdapDynamicGroup.StaticUnit staticUnit = group.getStaticUnit();
/*  9867 */       Set<String> existingAddrs = staticUnit.getMembersSet();
/*  9868 */       List<String> addrsToAdd = Lists.newArrayList();
/*  9869 */       for (String addr : externalAddrs) {
/*  9870 */         if (!existingAddrs.contains(addr)) {
/*  9871 */           addrsToAdd.add(addr);
/*       */         }
/*       */       }
/*       */       
/*  9875 */       if (!addrsToAdd.isEmpty()) {
/*  9876 */         Map<String, String[]> attrs = new HashMap();
/*  9877 */         attrs.put("+zimbraMailForwardingAddress", addrsToAdd.toArray(new String[addrsToAdd.size()]));
/*       */         
/*  9879 */         modifyLdapAttrs(staticUnit, zlc, attrs);
/*       */       }
/*       */     }
/*       */     finally {
/*  9883 */       LdapClient.closeContext(zlc);
/*       */     }
/*  9885 */     PermissionCache.invalidateCache();
/*  9886 */     cleanGroupMembersCache(group);
/*       */   }
/*       */   
/*       */   private void removeDynamicGroupExternalMembers(LdapDynamicGroup group, String[] members) throws ServiceException
/*       */   {
/*  9891 */     removeDynamicGroupMembers(group, members, true);
/*       */   }
/*       */   
/*       */   private void removeDynamicGroupMembers(LdapDynamicGroup group, String[] members, boolean externalOnly) throws ServiceException
/*       */   {
/*  9896 */     if (group.isMembershipDefinedByCustomURL()) {
/*  9897 */       throw ServiceException.INVALID_REQUEST(String.format("cannot remove members from dynamic group '%s' with custom memberURL", new Object[] { group.getName() }), null);
/*       */     }
/*       */     
/*       */ 
/*       */ 
/*  9902 */     String groupId = group.getId();
/*       */     
/*  9904 */     List<Account> accts = new ArrayList();
/*  9905 */     List<String> externalAddrs = new ArrayList();
/*  9906 */     HashSet<String> failed = new HashSet();
/*       */     
/*       */ 
/*  9909 */     for (String member : members) {
/*  9910 */       String memberName = member.toLowerCase();
/*       */       
/*  9912 */       boolean isBadAddr = false;
/*       */       try {
/*  9914 */         memberName = IDNUtil.toAsciiEmail(memberName);
/*       */       }
/*       */       catch (ServiceException e)
/*       */       {
/*  9918 */         memberName = member;
/*  9919 */         isBadAddr = true;
/*       */       }
/*       */       
/*       */ 
/*  9923 */       externalAddrs.add(memberName);
/*       */       
/*  9925 */       if (!externalOnly) {
/*  9926 */         Account acct = isBadAddr ? null : get(Key.AccountBy.name, member);
/*  9927 */         if (acct != null) {
/*  9928 */           Set<String> memberOf = acct.getMultiAttrSet("zimbraMemberOf");
/*  9929 */           if (memberOf.contains(groupId)) {
/*  9930 */             accts.add(acct);
/*       */           }
/*       */           else {
/*  9933 */             failed.add(memberName);
/*       */           }
/*       */         }
/*       */       }
/*       */     }
/*       */     
/*  9939 */     if (!failed.isEmpty()) {
/*  9940 */       StringBuilder sb = new StringBuilder();
/*  9941 */       Iterator<String> iter = failed.iterator();
/*       */       for (;;) {
/*  9943 */         sb.append((String)iter.next());
/*  9944 */         if (!iter.hasNext())
/*       */           break;
/*  9946 */         sb.append(",");
/*       */       }
/*  9948 */       throw AccountServiceException.NO_SUCH_MEMBER(group.getName(), sb.toString());
/*       */     }
/*       */     
/*  9951 */     ZLdapContext zlc = null;
/*       */     try {
/*  9953 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.REMOVE_GROUP_MEMBER);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  9958 */       for (Account acct : accts) {
/*  9959 */         Map<String, Object> attrs = new HashMap();
/*  9960 */         attrs.put("-zimbraMemberOf", groupId);
/*  9961 */         modifyLdapAttrs(acct, zlc, attrs);
/*  9962 */         clearUpwardMembershipCache(acct);
/*       */       }
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*  9968 */       LdapDynamicGroup.StaticUnit staticUnit = group.getStaticUnit();
/*  9969 */       Set<String> existingAddrs = staticUnit.getMembersSet();
/*  9970 */       List<String> addrsToRemove = Lists.newArrayList();
/*  9971 */       for (String addr : externalAddrs) {
/*  9972 */         if (existingAddrs.contains(addr)) {
/*  9973 */           addrsToRemove.add(addr);
/*       */         }
/*       */       }
/*       */       
/*  9977 */       if (!addrsToRemove.isEmpty()) {
/*  9978 */         Map<String, String[]> attrs = new HashMap();
/*  9979 */         attrs.put("-zimbraMailForwardingAddress", addrsToRemove.toArray(new String[addrsToRemove.size()]));
/*       */         
/*  9981 */         modifyLdapAttrs(staticUnit, zlc, attrs);
/*       */       }
/*       */     }
/*       */     finally {
/*  9985 */       LdapClient.closeContext(zlc);
/*       */     }
/*  9987 */     PermissionCache.invalidateCache();
/*  9988 */     cleanGroupMembersCache(group);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private List<DynamicGroup> getContainingDynamicGroups(Account acct)
/*       */     throws ServiceException
/*       */   {
/* 10000 */     List<DynamicGroup> groups = new ArrayList();
/*       */     
/* 10002 */     Set<String> memberOf = getAllContainingDynamicGroupIDs(acct);
/* 10003 */     for (String groupId : memberOf) {
/* 10004 */       DynamicGroup dynGroup = getDynamicGroupBasic(Key.DistributionListBy.id, groupId, null);
/* 10005 */       if ((dynGroup != null) && (!dynGroup.isMembershipDefinedByCustomURL())) {
/* 10006 */         groups.add(dynGroup);
/*       */       }
/*       */     }
/*       */     
/* 10010 */     return groups;
/*       */   }
/*       */   
/*       */   private Set<String> getAllContainingDynamicGroupIDs(Account acct)
/*       */     throws ServiceException
/*       */   {
/*       */     Set<String> memberOf;
/*       */     Set<String> memberOf;
/* 10018 */     if ((acct instanceof GuestAccount)) {
/* 10019 */       memberOf = searchContainingDynamicGroupIdsForExternalAddress(acct.getName(), null); } else { Set<String> memberOf;
/* 10020 */       if (acct.isIsExternalVirtualAccount()) {
/* 10021 */         memberOf = searchContainingDynamicGroupIdsForExternalAddress(acct.getExternalUserMailAddress(), null);
/*       */       } else
/* 10023 */         memberOf = acct.getMultiAttrSet("zimbraMemberOf");
/*       */     }
/* 10025 */     return memberOf;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */   private Set<String> searchContainingDynamicGroupIdsForExternalAddress(String addr, ZLdapContext initZlc)
/*       */   {
/* 10033 */     final Set<String> groupIds = Sets.newHashSet();
/*       */     
/* 10035 */     SearchLdapOptions.SearchLdapVisitor visitor = new SearchLdapOptions.SearchLdapVisitor(false)
/*       */     {
/*       */       public void visit(String dn, IAttributes ldapAttrs) throws SearchLdapOptions.StopIteratingException
/*       */       {
/* 10039 */         String groupId = null;
/*       */         try {
/* 10041 */           groupId = ldapAttrs.getAttrString("zimbraGroupId");
/*       */         } catch (ServiceException e) {
/* 10043 */           ZimbraLog.account.warn("unable to get attr", e);
/*       */         }
/* 10045 */         if (groupId != null) {
/* 10046 */           groupIds.add(groupId);
/*       */         }
/*       */         
/*       */       }
/* 10050 */     };
/* 10051 */     ZLdapContext zlc = initZlc;
/*       */     try {
/* 10053 */       if (zlc == null) {
/* 10054 */         zlc = LdapClient.getContext(LdapServerType.REPLICA, LdapUsage.SEARCH);
/*       */       }
/* 10056 */       String base = this.mDIT.mailBranchBaseDN();
/* 10057 */       ZLdapFilter filter = this.filterFactory.dynamicGroupsStaticUnitByMemberAddr(addr);
/*       */       
/*       */ 
/* 10060 */       SearchLdapOptions searchOptions = new SearchLdapOptions(base, filter, new String[] { "zimbraGroupId" }, 0, null, ZSearchScope.SEARCH_SCOPE_SUBTREE, visitor);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/* 10065 */       zlc.searchPaged(searchOptions);
/*       */     }
/*       */     catch (ServiceException e) {
/* 10068 */       ZimbraLog.account.warn("unable to search dynamic groups for guest acct", e);
/*       */     } finally {
/* 10070 */       if (initZlc == null) {
/* 10071 */         LdapClient.closeContext(zlc);
/*       */       }
/*       */     }
/*       */     
/* 10075 */     return groupIds;
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private void removeExternalAddrsFromAllDynamicGroups(Set<String> addrs, ZLdapContext zlc)
/*       */     throws ServiceException
/*       */   {
/* 10086 */     for (Iterator i$ = addrs.iterator(); i$.hasNext();) { addr = (String)i$.next();
/* 10087 */       Set<String> memberOf = searchContainingDynamicGroupIdsForExternalAddress(addr, zlc);
/*       */       
/* 10089 */       for (String groupId : memberOf) {
/* 10090 */         DynamicGroup group = getDynamicGroupBasic(Key.DistributionListBy.id, groupId, zlc);
/* 10091 */         if (group != null) {
/* 10092 */           removeDynamicGroupExternalMembers((LdapDynamicGroup)group, new String[] { addr });
/*       */         }
/*       */       }
/*       */     }
/*       */     String addr;
/*       */   }
/*       */   
/*       */   private List<String> searchDynamicGroupMembers(DynamicGroup group)
/*       */     throws ServiceException
/*       */   {
/* 10102 */     if (group.isMembershipDefinedByCustomURL()) {
/* 10103 */       throw ServiceException.INVALID_REQUEST("cannot search members to dynamic group with custom memberURL", null);
/*       */     }
/*       */     
/*       */ 
/* 10107 */     List<String> members = Lists.newArrayList();
/*       */     
/* 10109 */     ZLdapContext zlc = null;
/*       */     try
/*       */     {
/* 10112 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.SEARCH);
/*       */       
/*       */ 
/* 10115 */       searchDynamicGroupInternalMemberDeliveryAddresses(zlc, group.getId(), members);
/*       */       
/*       */ 
/* 10118 */       LdapDynamicGroup.StaticUnit staticUnit = ((LdapDynamicGroup)group).getStaticUnit();
/*       */       
/*       */ 
/* 10121 */       refreshEntry(staticUnit, zlc);
/* 10122 */       for (String extAddr : staticUnit.getMembers()) {
/* 10123 */         members.add(extAddr);
/*       */       }
/*       */     } catch (ServiceException e) {
/* 10126 */       ZimbraLog.account.warn("unable to search dynamic group members", e);
/*       */     } finally {
/* 10128 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/*       */ 
/* 10132 */     return members;
/*       */   }
/*       */   
/*       */ 
/*       */   private void searchDynamicGroupInternalMemberDeliveryAddresses(ZLdapContext initZlc, String dynGroupId, final Collection<String> result)
/*       */   {
/* 10138 */     SearchLdapOptions.SearchLdapVisitor visitor = new SearchLdapOptions.SearchLdapVisitor(false)
/*       */     {
/*       */       public void visit(String dn, IAttributes ldapAttrs) throws SearchLdapOptions.StopIteratingException {
/* 10141 */         String addr = null;
/*       */         try {
/* 10143 */           addr = ldapAttrs.getAttrString("zimbraMailDeliveryAddress");
/*       */         } catch (ServiceException e) {
/* 10145 */           ZimbraLog.account.warn("unable to get attr", e);
/*       */         }
/* 10147 */         if (addr != null) {
/* 10148 */           result.add(addr);
/*       */         }
/*       */         
/*       */       }
/* 10152 */     };
/* 10153 */     ZLdapContext zlc = initZlc;
/*       */     try {
/* 10155 */       if (zlc == null)
/*       */       {
/* 10157 */         zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.SEARCH);
/*       */       }
/* 10159 */       searchDynamicGroupInternalMembers(zlc, dynGroupId, visitor);
/*       */     } catch (ServiceException e) {
/* 10161 */       ZimbraLog.account.warn("unable to search dynamic group members", e);
/*       */     } finally {
/* 10163 */       if (initZlc == null) {
/* 10164 */         LdapClient.closeContext(zlc);
/*       */       }
/*       */     }
/*       */   }
/*       */   
/*       */   public String[] getNonDefaultDynamicGroupMembers(DynamicGroup group) {
/* 10170 */     List<String> members = Lists.newArrayList();
/*       */     
/* 10172 */     ZLdapContext zlc = null;
/*       */     try {
/* 10174 */       zlc = LdapClient.getContext(LdapServerType.REPLICA, LdapUsage.GET_GROUP_MEMBER);
/*       */       
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/* 10180 */       String[] memberDNs = group.getMultiAttr("member");
/*       */       
/* 10182 */       String[] attrsToGet = { "zimbraMailDeliveryAddress", "zimbraIsExternalVirtualAccount" };
/*       */       
/* 10184 */       for (String memberDN : memberDNs) {
/* 10185 */         ZAttributes memberAttrs = zlc.getAttributes(memberDN, attrsToGet);
/* 10186 */         String memberAddr = memberAttrs.getAttrString("zimbraMailDeliveryAddress");
/*       */         
/* 10188 */         boolean isVirtualAcct = memberAttrs.hasAttributeValue("zimbraIsExternalVirtualAccount", "TRUE");
/*       */         
/* 10190 */         if ((memberAddr != null) && (!isVirtualAcct)) {
/* 10191 */           members.add(memberAddr);
/*       */         }
/*       */       }
/*       */     }
/*       */     catch (ServiceException e) {
/* 10196 */       ZimbraLog.account.warn("unable to get dynamic group members", e);
/*       */     } finally {
/* 10198 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */     
/* 10201 */     return (String[])members.toArray(new String[members.size()]);
/*       */   }
/*       */   
/*       */   public String[] getDynamicGroupMembers(DynamicGroup group) throws ServiceException {
/* 10205 */     List<String> members = searchDynamicGroupMembers(group);
/* 10206 */     return (String[])members.toArray(new String[members.size()]);
/*       */   }
/*       */   
/*       */   public Set<String> getDynamicGroupMembersSet(DynamicGroup group) throws ServiceException {
/* 10210 */     List<String> members = searchDynamicGroupMembers(group);
/* 10211 */     return Sets.newHashSet(members);
/*       */   }
/*       */   
/*       */ 
/*       */ 
/*       */ 
/*       */ 
/*       */   private UCService getUCServiceByQuery(ZLdapFilter filter, ZLdapContext initZlc)
/*       */     throws ServiceException
/*       */   {
/*       */     try
/*       */     {
/* 10223 */       ZSearchResultEntry sr = this.helper.searchForEntry(this.mDIT.ucServiceBaseDN(), filter, initZlc, false);
/* 10224 */       if (sr != null) {
/* 10225 */         return new LdapUCService(sr.getDN(), sr.getAttributes(), this);
/*       */       }
/*       */     } catch (LdapException.LdapMultipleEntriesMatchedException e) {
/* 10228 */       throw AccountServiceException.MULTIPLE_ENTRIES_MATCHED("getUCServiceByQuery", e);
/*       */     } catch (ServiceException e) {
/* 10230 */       throw ServiceException.FAILURE("unable to lookup ucservice via query: " + filter.toFilterString() + " message:" + e.getMessage(), e);
/*       */     }
/*       */     
/* 10233 */     return null;
/*       */   }
/*       */   
/*       */   private UCService getUCServiceById(String zimbraId, ZLdapContext zlc, boolean nocache) throws ServiceException
/*       */   {
/* 10238 */     if (zimbraId == null) {
/* 10239 */       return null;
/*       */     }
/* 10241 */     UCService s = null;
/* 10242 */     if (!nocache) {
/* 10243 */       s = (UCService)this.ucServiceCache.getById(zimbraId);
/*       */     }
/* 10245 */     if (s == null) {
/* 10246 */       s = getUCServiceByQuery(this.filterFactory.ucServiceById(zimbraId), zlc);
/* 10247 */       this.ucServiceCache.put(s);
/*       */     }
/* 10249 */     return s;
/*       */   }
/*       */   
/*       */   private UCService getUCServiceByName(String name, boolean nocache) throws ServiceException {
/* 10253 */     if (!nocache) {
/* 10254 */       UCService s = (UCService)this.ucServiceCache.getByName(name);
/* 10255 */       if (s != null) {
/* 10256 */         return s;
/*       */       }
/*       */     }
/*       */     try
/*       */     {
/* 10261 */       String dn = this.mDIT.ucServiceNameToDN(name);
/* 10262 */       ZAttributes attrs = this.helper.getAttributes(LdapUsage.GET_UCSERVICE, dn);
/* 10263 */       LdapUCService s = new LdapUCService(dn, attrs, this);
/* 10264 */       this.ucServiceCache.put(s);
/* 10265 */       return s;
/*       */     } catch (LdapException.LdapEntryNotFoundException e) {
/* 10267 */       return null;
/*       */     } catch (ServiceException e) {
/* 10269 */       throw ServiceException.FAILURE("unable to lookup ucservice by name: " + name + " message: " + e.getMessage(), e);
/*       */     }
/*       */   }
/*       */   
/*       */   public UCService createUCService(String name, Map<String, Object> attrs)
/*       */     throws ServiceException
/*       */   {
/* 10276 */     name = name.toLowerCase().trim();
/*       */     
/* 10278 */     CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
/* 10279 */     AttributeManager.getInstance().preModify(attrs, null, callbackContext, true);
/*       */     
/* 10281 */     ZLdapContext zlc = null;
/*       */     try {
/* 10283 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_UCSERVICE);
/*       */       
/* 10285 */       ZMutableEntry entry = LdapClient.createMutableEntry();
/* 10286 */       entry.mapToAttrs(attrs);
/*       */       
/* 10288 */       Set<String> ocs = LdapObjectClass.getUCServiceObjectClasses(this);
/* 10289 */       entry.addAttr("objectClass", ocs);
/*       */       
/* 10291 */       String zimbraIdStr = LdapUtil.generateUUID();
/* 10292 */       entry.setAttr("zimbraId", zimbraIdStr);
/* 10293 */       entry.setAttr("zimbraCreateTimestamp", DateUtil.toGeneralizedTime(new Date()));
/* 10294 */       entry.setAttr("cn", name);
/* 10295 */       String dn = this.mDIT.ucServiceNameToDN(name);
/*       */       
/* 10297 */       entry.setDN(dn);
/* 10298 */       zlc.createEntry(entry);
/*       */       
/* 10300 */       UCService ucService = getUCServiceById(zimbraIdStr, zlc, true);
/* 10301 */       AttributeManager.getInstance().postModify(attrs, ucService, callbackContext);
/* 10302 */       return ucService;
/*       */     }
/*       */     catch (LdapException.LdapEntryAlreadyExistException nabe) {
/* 10305 */       throw AccountServiceException.SERVER_EXISTS(name);
/*       */     } catch (LdapException e) {
/* 10307 */       throw e;
/*       */     } catch (AccountServiceException e) {
/* 10309 */       throw e;
/*       */     } catch (ServiceException e) {
/* 10311 */       throw ServiceException.FAILURE("unable to create ucservice: " + name, e);
/*       */     } finally {
/* 10313 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public void deleteUCService(String zimbraId) throws ServiceException
/*       */   {
/* 10319 */     LdapUCService ucService = (LdapUCService)getUCServiceById(zimbraId, null, false);
/* 10320 */     if (ucService == null) {
/* 10321 */       throw AccountServiceException.NO_SUCH_UC_SERVICE(zimbraId);
/*       */     }
/*       */     
/* 10324 */     ZLdapContext zlc = null;
/*       */     try {
/* 10326 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.DELETE_UCSERVICE);
/* 10327 */       zlc.deleteEntry(ucService.getDN());
/* 10328 */       this.ucServiceCache.remove(ucService);
/*       */     } catch (ServiceException e) {
/* 10330 */       throw ServiceException.FAILURE("unable to purge ucservice: " + zimbraId, e);
/*       */     } finally {
/* 10332 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public UCService get(Key.UCServiceBy keyType, String key) throws ServiceException
/*       */   {
/* 10338 */     switch (keyType) {
/*       */     case name: 
/* 10340 */       return getUCServiceByName(key, false);
/*       */     case id: 
/* 10342 */       return getUCServiceById(key, null, false);
/*       */     }
/* 10344 */     return null;
/*       */   }
/*       */   
/*       */   public List<UCService> getAllUCServices()
/*       */     throws ServiceException
/*       */   {
/* 10350 */     List<UCService> result = new ArrayList();
/*       */     
/* 10352 */     ZLdapFilter filter = this.filterFactory.allUCServices();
/*       */     try
/*       */     {
/* 10355 */       ZSearchResultEnumeration ne = this.helper.searchDir(this.mDIT.ucServiceBaseDN(), filter, ZSearchControls.SEARCH_CTLS_SUBTREE());
/*       */       
/* 10357 */       while (ne.hasMore()) {
/* 10358 */         ZSearchResultEntry sr = ne.next();
/* 10359 */         LdapUCService s = new LdapUCService(sr.getDN(), sr.getAttributes(), this);
/* 10360 */         result.add(s);
/*       */       }
/* 10362 */       ne.close();
/*       */     } catch (ServiceException e) {
/* 10364 */       throw ServiceException.FAILURE("unable to list all servers", e);
/*       */     }
/*       */     
/* 10367 */     if (result.size() > 0) {
/* 10368 */       this.ucServiceCache.put(result, true);
/*       */     }
/* 10370 */     Collections.sort(result);
/* 10371 */     return result;
/*       */   }
/*       */   
/*       */   public void renameUCService(String zimbraId, String newName) throws ServiceException
/*       */   {
/* 10376 */     LdapUCService ucService = (LdapUCService)getUCServiceById(zimbraId, null, false);
/* 10377 */     if (ucService == null) {
/* 10378 */       throw AccountServiceException.NO_SUCH_UC_SERVICE(zimbraId);
/*       */     }
/*       */     
/* 10381 */     ZLdapContext zlc = null;
/*       */     try {
/* 10383 */       zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_UCSERVICE);
/* 10384 */       String newDn = this.mDIT.ucServiceNameToDN(newName);
/* 10385 */       zlc.renameEntry(ucService.getDN(), newDn);
/* 10386 */       this.ucServiceCache.remove(ucService);
/*       */     } catch (LdapException.LdapEntryAlreadyExistException nabe) {
/* 10388 */       throw AccountServiceException.UC_SERVICE_EXISTS(newName);
/*       */     } catch (LdapException e) {
/* 10390 */       throw e;
/*       */     } catch (AccountServiceException e) {
/* 10392 */       throw e;
/*       */     } catch (ServiceException e) {
/* 10394 */       throw ServiceException.FAILURE("unable to rename ucservice: " + zimbraId, e);
/*       */     } finally {
/* 10396 */       LdapClient.closeContext(zlc);
/*       */     }
/*       */   }
/*       */   
/*       */   public boolean isCacheEnabled()
/*       */   {
/* 10402 */     return this.useCache;
/*       */   }
/*       */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/account/ldap/LdapProvisioning.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */